bootstrap=no suppresses nothing: the composite drops the input and the script gates on the event name, so every trigger-woken sweep re-upserts the whole taxonomy
#466
Replies: 2 comments
|
Ruled and minted: #472 — @danmt took R1 at Three things the issue carries that this thread did not:
Minted Converged; closing. Further findings on the gate belong on #472. |
Uh oh!
There was an error while loading. Please reload this page.
Triage finding,
2026-08-17T07:2xZ, measured at663ba83(main). Filing rather than minting — see the last section for why, and for what I am not asking anyone to decide today.The finding
actions/labels-reconcile'sbootstrapinput cannot suppress the bootstrap. It works in one direction only:action.yml:39-43and the script's only gate is the event name —
grep -n BOOTSTRAP actions/labels-reconcile/labels-reconcile.shreturns nothing, so the variableaction.ymlcarefully places in the step's env is read by no line of the subject:labels-reconcile.sh:1151-1154A trigger-woken sweep already arrives as
workflow_dispatch— that is howlabels.yml:138wakes it, and the anti-recursion exemption that lets it do so with no PAT is the whole reason it is a dispatch:So
yesforces a state thatnois powerless to leave. The input is dead: the operator's manual full-board bootstrap and an event-woken sweep are indistinguishable to the script, which is the exact thing the input was added to fix.The design says otherwise, in three places
labels-sweep.yml:23-27— "The trigger job's dispatches carrybootstrap=no— ~20 label upserts per sweep is too chatty for every board event, the same reason cron runs never bootstrapped."labels-sweep.yml:104-110— "the event name alone no longer separates the operator's manual full-board bootstrap from an event-woken sweep — the caller'sbootstrapdispatch input does: the trigger passes"no", a bare manual dispatch defaults to"yes"."docs/CONSUMERS.md:815-817— "Scheduled and trigger-driven runs only reconcile; they do not repeatedly upsert the taxonomy (the trigger's dispatch carriesbootstrap=no)." Published to every consumer, and false in its second clause.The caller itself is correct and does real work computing a value nothing consumes —
labels-sweep.yml:115and its dogfood twin at:125both evaluateThe cron path is fine, and that is worth stating precisely: a
scheduleevent is notworkflow_dispatch, so the scheduled sweep genuinely does not bootstrap. Only the trigger-woken runs are affected — which is nearly all of them.Measured live, in this repository, four minutes ago
Not carried from my #423 incubator measurement — re-measured here, in ceremony, on run 32004881752, which my own issue-body write at
07:13:32Zwoke:The input said
no; the taxonomy was bootstrapped anyway, 21 milliseconds later.What it costs
07:13:48.94 → 07:13:58.50, and the six retire probes follow. Roughly four fifths of the step.gh api /repos/heavy-duty/ceremony/labels --paginate), upserted on every trigger-woken sweep.self-labels-sweep.ymlspan2026-08-16T11:05:26Z → 2026-08-17T07:17:11Z, 20 h 12 m. Not every dispatch pays it — concurrency cancels a displaced run — but a completing one pays it in full.Why it matters beyond the runner minutes
This is the mechanism behind the thing I published, retracted and re-published on #423 yesterday: a core label added by a pin bump arrives in a consumer's taxonomy with no operator act, on the first board event after the bump. Convenient, undocumented, and the direct opposite of what
docs/CONSUMERS.md:817-819instructs a consumer to do ("bump the pin first and then re-dispatch"). Fixing the input restores the documented world — andmissing_core_labels_warningis already there to nag the consumer who has not dispatched, so the machinery for that world is built.So the repair is not only a saving; it is a consumer-visible behaviour change, and that is the part worth a second opinion rather than my say-so.
Two candidate repairs
R1 — make the script read the input (recommended).
labels-reconcile.shgates on an explicitBOOTSTRAPvariable — the oneaction.ymlalready exports and nothing reads — andaction.ymlstops rewritingGITHUB_EVENT_NAME. The caller's computed value becomes load-bearing, which is what every comment above already claims. Nothing else in the script readsGITHUB_EVENT_NAME(grepfinds the single site quoted above), so the blast radius is the gate itself plus the fixtures that drive it.R2 — force the event name in both directions.
action.ymlexportsGITHUB_EVENT_NAME=workflow_dispatchonyesand something else onno. One line, no change to the script or the test surface. But it makes the composite lie about the event to anything that later reads it, and the next reader has to rediscover why.Recommend R1, on the ground that R2 keeps the defect's shape — a gate reading a fact that is not the question being asked — and this is the second time that shape has cost a wrong published claim.
Class, and what I am not doing
Ordinary, not front row: it breaks no build, mislabels no board, and reds no consumer. It is cost plus a false published sentence, and TRIAGE.md says an uncertain class takes ordinary. Its deliverable is
actions/labels-reconcile/labels-reconcile.sh, which #460 is rewriting and #461 extends — so a minted issue takes an unconditional collision edge behind the newest open carrier and lands at the end of that chain. Nothing here asks for a label to move on work in flight.I have not minted it, and this is not a ruling ask — no options table, no default, no clock. @danmt has a live decision in front of him on #464 and this one holds nothing. If nobody objects to R1, I will converge this and mint on a later pass; if the unasked-label arrival turns out to be behaviour anyone wants to keep, say so here and the repair becomes documenting it instead.
All reactions