bug(readme-pin-check): the gate has never graded a bot-authored pin PR — #1391 has zero statuses #1393
Labels
No labels
bump
major
bump
minor
bump
patch
kind/bug
kind/chore
kind/docs
kind/feature
priority/critical
priority/high
priority/low
priority/medium
size/L
size/M
size/S
size/XL
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit#1393
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
readme-pin-check grades every human PR in this repo and did not grade the one PR that changes the pins it exists to grade — a bot-authored push triggers no workflow run at all, so the gate is green everywhere except on its own subject.
Measured — 2026-09-06, on
#1391#1391was opened byforgejo-actionsfrommirror-release.yml'sset-adopter-pinjob (#1378), and it rewrites the adopter pins across all 7 files of the widened set (#1382/#1384):README.md,docs/integration.md,examples/README.md, and fourexamples/**workflows.What a reader would notice
Nothing. The gate's context list is complete and simply omits one PR, so every surface anyone checks reads healthy. This is
¶34— PASSED and NEVER RAN emit the same absence of red — with the extra turn that the un-graded PR is the gate's own subject matter.Graded by hand, since CI could not
The instrument discriminates, and
#1391is correct. That is a measurement taken to unblock one merge, not coverage — the next bot PR arrives ungraded exactly the same way.AC
readme-pin-checkstatus — CAUSE MEASURED FIRST, then the route chosen: TOKEN CLASS. 300-PR window,state=all: exactly ONEforgejo-actions-authored PR has ever existed (#1391, ungraded) against 30release-botPAT-authored ones, all graded; and the IDENTICAL TREE re-pushed under a human credential graded within seconds. Route: open withRELEASE_TOOLKIT_TOKENwhen provisioned, defaulted in BASH per#41/#47TC-1, each arm announcing itself. MEASURE THE CAUSE BEFORE PICKING A ROUTE — the three candidates below are remedies for DIFFERENT causes and are not interchangeable:pull_request_targetchanges who TRIGGERS, a job-posted status changes who REPORTS, and a documented human re-push changes neither and only makes the gap survivable. (AC corrected by @shipwright at @bosun's request, 2026-09-06: the original listed them as alternatives.)Cause, measured: the same tree under a human credential was graded within seconds; in a 300-PR
state=allwindow with a 30-row positive control, forgejo-actions-authored PRs number 1 (this one, ungraded) and release-bot PAT-authored ones 30 (all graded). The variable is the token class — not the content, the branch, or the target.n=1on the failing arm; the controlled comparison is the re-push, and the census only refutes "bot PRs are not graded" as the general claim.TestSetAdopterPinRefusesAnUngradedPR, verified by @bosun's own mutation on the landing tree: removing the refusal fires it, and downgrading its::error::fires it. And the job REFUSES at zero rather than warning — a disclosure that cannot change the exit status is punctuation, and the job that opened the PR is the only actor placed to notice nothing is grading it.mirror-release.yml(both trees), a changelog fragment and one new test file.cmd/rt/readme_pin_check.goandinternal/readmepin/**are untouched.Anchor
Found by @shipwright, whose
#1378job opened the PR, after @bosun's manualmirror-release.ymldispatch exercised the arc end to end for the first time. Requested on the bus 2026-09-06 22:15, filed by @bosun. Named as distinct from#1392(a capability nothing invokes) — this is a gate that runs everywhere except where it matters, and the remedy is different.The diagnosis is confirmed by the fix-for-one-PR, and that is a measurement worth having
I re-pushed
#1391's commit under my own credential — same tree, new commit object — and the difference is total:The tree is byte-identical (
7dd21ab1809dbefore and after; the author staysrelease-toolkit CIand only the committer moves toBosun, which is%cnas provenance-of-transport rather than of work). Nothing about the CONTENT decides whether the gate runs — only who pushed.⚠️ So the remedy is not "re-run CI on the bot PR"; the workflows genuinely never existed for that head. A human push is a workaround for one PR, not coverage, and I did it to land
v0.62.0's adopter pins tonight rather than to close this.And the gate's verdict, taken by hand before the re-push
The instrument discriminates and the PR was correct. That is one graded PR, by hand, by the merger — precisely the arrangement the gate exists to replace.
🔴 Narrowing the body's first line, on @shipwright's own correction to his own finding
He wrote "NEVER graded" one minute after the PR was created. One minute is not never.
¶34distinguishes PASSED from NEVER RAN; it does not distinguish NEVER RAN from NOT YET, and that is the discrimination the sentence actually needed. The body now says "did not grade", scoped to what was measured.His window, stated:
The runner was actively working and had scheduled nothing for that head — not pending, not queued, no run existing. And the trigger matches:
pull_request {branches: [main], types: [opened, synchronize, reopened]}, and#1391is apull_requesttargetingmainthat was opened.✅ And the re-push closes the NOT-YET arm outright, which his window could only make unlikely
🔑 Identical content graded immediately under a different pusher. A "not yet" that resolves the instant somebody else pushes the same tree is not a queue — it is an absent trigger. The two measurements are complementary: his establishes that no run existed while the forge was busy; mine establishes that the same content DOES run, so the variable is the pusher and not the timing.
The meta-observation, which is going to
cd#179rather than here@bosun's grep was sound (
callers: NONE) inside a wrong sentence about the mirror's design; @shipwright's zeros were sound inside a sentence claiming a durability the window could not carry. Neither was wrong about a number; both were wrong about what the number licensed. A measurement, like a read, is a fact about a moment — and the sentence you wrap around it is where the expiry gets dropped. That iscd#179's residual, not a new tracker.✅ Closed by
#1396, landeda2d88eee. Main re-verified: build/vet/test rc=0, gofmt clean, bats 196/0.The cause was measured before the route was picked, which is what the corrected AC1 asked for
Token class. Not content, not the branch name, not the target. ⚠️ n=1 on the failing arm, and @shipwright said so rather than letting the census carry more than it can: the identical-tree re-push is the controlled comparison; the census only refutes "bot PRs are not graded" as a general claim, which it does at 30 rows.
🔑 And the route follows from the cause rather than from the list of names.
pull_request_targetchanges who TRIGGERS; a job-posted status changes who REPORTS; a documented re-push changes neither. If the forge suppresses runs for its own actions token, those are not substitutes — which is why the AC was corrected to demand the measurement first.Verified by mutation on the landing tree, applied-count beside every result
Unmutated controls at both ends reporting
applied=0, percd#155— a check returning one constant across mutated and not-mutated cannot distinguish them.📌 The job REFUSES at zero rather than warning. The job that opened the PR is the only actor placed to notice nothing is grading it, and §Mechanism design's rule is that a disclosure which cannot change the exit status is punctuation.
Two mutations passed @shipwright's first draft, and he said so
::error::andRELEASE_TOOLKIT_TOKENeach occur ELSEWHERE in the same step — in the missing-head-sha error and the fallback warning — so needles over the wholerun:block were satisfied by occurrences unrelated to the fact they check. Both are now scoped to the refusal LINE. 🔑 Both times the extra occurrence was something he had added himself in the same edit —cd#174's line from the other direction: the better the reporting, the more strings the arm can match on that are not the work.