Skip to content

Commit 89f74f2

Browse files
committed
feat(tooling): ban the whole-set label PUT in every spelling (#10778)
#10703 made both label writers in pr-automation.yml additive, removing the two whole-set `PUT /issues/{n}/labels` writes. It could not make the verb unavailable: nothing stopped a new third-party labeler or a second workflow from reopening the same defect, and the only guard was a prose paragraph. The gate asserts the card's three assertions over .github/workflows/**, .github/actions/** and scripts/**: no PUT against the labels endpoint in any spelling; no `uses:` of an action measured to write the whole set; and an allowlist entry requires a stated reason, enforced by a refusal rather than by the self-test alone. Only executable content is judged -- the two files that document the ban spell every forbidden form in comments, so a raw-text matcher would red on the documentation of its own rule. The same matcher runs over raw and comment-blanked text and both counts are printed, and PROSE_PROBES declares the live prose that must keep matching, so the judged zero is a measurement rather than a silence. Measured: 194 files, 11 raw mentions all cleared as comments, 0 executable, 147 `uses:` pins over 18 distinct actions judged, 0 violations, 0 allowlist entries. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015ahemw8RcTgqtxrj15PEZx
1 parent 387e231 commit 89f74f2

2 files changed

Lines changed: 956 additions & 0 deletions

File tree

.github/workflows/lint.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1836,6 +1836,46 @@ jobs:
18361836
- name: Additive label-write self-test
18371837
run: node scripts/pr-labels.mjs --self-test
18381838

1839+
# The other half of that contract (#10778, split out of #10703). The step
1840+
# above proves ONE script never emits a whole-set write; this one proves
1841+
# nothing in the repo does. #10703 removed the two whole-set
1842+
# `PUT /issues/{n}/labels` writes, but it could not make the verb
1843+
# UNAVAILABLE -- a newly added third-party labeler, or a second workflow
1844+
# calling the endpoint directly, reopens the same defect, and until this
1845+
# gate the only guard was a prose paragraph in pr-automation.yml's header.
1846+
#
1847+
# A whole-set PUT destroys any label that lands between its read and its
1848+
# write. Its second-order cost is the expensive one: while the verb is
1849+
# reachable, "the label is absent" stops meaning anything, because absence
1850+
# has two causes (cleared deliberately, or erased) and read-back is the
1851+
# only detection there is.
1852+
#
1853+
# Three assertions, all from the card: no PUT against the labels endpoint
1854+
# in ANY spelling (`curl -X PUT`, `gh api --method PUT`, `issues.setLabels`,
1855+
# `octokit.request('PUT /repos/...')`, a `method: 'PUT'` fetch); no `uses:`
1856+
# of an action measured to write the whole set; and an allowlist entry
1857+
# REQUIRES a stated reason -- the gate refuses rather than passes on an
1858+
# entry without one.
1859+
#
1860+
# Invoked as `node` rather than through a `pnpm check:*` alias, same as the
1861+
# other `node scripts/...` steps in this lane: that alias is a line in root
1862+
# package.json, inside the @changesets/cli v3 fence (#9465).
1863+
#
1864+
# Its --self-test runs first and is not ceremony. The gate is GREEN OVER AN
1865+
# EMPTY EXECUTABLE POPULATION -- every mention of the verb on this tree is
1866+
# in the comments that document the ban -- so a passing run over real data
1867+
# cannot by itself distinguish a working matcher from one that matches
1868+
# nothing. Two things answer that: the verdict line prints the judged
1869+
# population (files, raw mentions, comment-cleared, executable, `uses:`
1870+
# pins) so a zero is a measurement rather than a silence, and the gate
1871+
# REFUSES if the declared live probes in PROSE_PROBES stop matching. The
1872+
# self-test drives the real sweep red over fixture trees on disk.
1873+
# Static text only, no build, so it belongs in this pre-build group.
1874+
- name: No whole-set label PUT anywhere in the repo (#10778) + its self-test
1875+
run: |
1876+
node scripts/check-whole-set-label-write.mjs --self-test
1877+
node scripts/check-whole-set-label-write.mjs
1878+
18391879
# Cross-repo closer outcome contract (#9595, and #9575 before it).
18401880
# `cross-repo-issue-closer.yml` carries ~150 lines of inline
18411881
# github-script, and it is code nobody has ever seen run: over the 1176

0 commit comments

Comments
 (0)