Skip to content

Commit ce56937

Browse files
os-steveclaude
andauthored
feat(tooling): ban the whole-set label PUT in every spelling (#10778) (#11880)
#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. Claude-Session: https://claude.ai/code/session_015ahemw8RcTgqtxrj15PEZx Co-authored-by: Claude <noreply@anthropic.com>
1 parent d18ae69 commit ce56937

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
@@ -1867,6 +1867,46 @@ jobs:
18671867
- name: Additive label-write self-test
18681868
run: node scripts/pr-labels.mjs --self-test
18691869

1870+
# The other half of that contract (#10778, split out of #10703). The step
1871+
# above proves ONE script never emits a whole-set write; this one proves
1872+
# nothing in the repo does. #10703 removed the two whole-set
1873+
# `PUT /issues/{n}/labels` writes, but it could not make the verb
1874+
# UNAVAILABLE -- a newly added third-party labeler, or a second workflow
1875+
# calling the endpoint directly, reopens the same defect, and until this
1876+
# gate the only guard was a prose paragraph in pr-automation.yml's header.
1877+
#
1878+
# A whole-set PUT destroys any label that lands between its read and its
1879+
# write. Its second-order cost is the expensive one: while the verb is
1880+
# reachable, "the label is absent" stops meaning anything, because absence
1881+
# has two causes (cleared deliberately, or erased) and read-back is the
1882+
# only detection there is.
1883+
#
1884+
# Three assertions, all from the card: no PUT against the labels endpoint
1885+
# in ANY spelling (`curl -X PUT`, `gh api --method PUT`, `issues.setLabels`,
1886+
# `octokit.request('PUT /repos/...')`, a `method: 'PUT'` fetch); no `uses:`
1887+
# of an action measured to write the whole set; and an allowlist entry
1888+
# REQUIRES a stated reason -- the gate refuses rather than passes on an
1889+
# entry without one.
1890+
#
1891+
# Invoked as `node` rather than through a `pnpm check:*` alias, same as the
1892+
# other `node scripts/...` steps in this lane: that alias is a line in root
1893+
# package.json, inside the @changesets/cli v3 fence (#9465).
1894+
#
1895+
# Its --self-test runs first and is not ceremony. The gate is GREEN OVER AN
1896+
# EMPTY EXECUTABLE POPULATION -- every mention of the verb on this tree is
1897+
# in the comments that document the ban -- so a passing run over real data
1898+
# cannot by itself distinguish a working matcher from one that matches
1899+
# nothing. Two things answer that: the verdict line prints the judged
1900+
# population (files, raw mentions, comment-cleared, executable, `uses:`
1901+
# pins) so a zero is a measurement rather than a silence, and the gate
1902+
# REFUSES if the declared live probes in PROSE_PROBES stop matching. The
1903+
# self-test drives the real sweep red over fixture trees on disk.
1904+
# Static text only, no build, so it belongs in this pre-build group.
1905+
- name: No whole-set label PUT anywhere in the repo (#10778) + its self-test
1906+
run: |
1907+
node scripts/check-whole-set-label-write.mjs --self-test
1908+
node scripts/check-whole-set-label-write.mjs
1909+
18701910
# Cross-repo closer outcome contract (#9595, and #9575 before it).
18711911
# `cross-repo-issue-closer.yml` carries ~150 lines of inline
18721912
# github-script, and it is code nobody has ever seen run: over the 1176

0 commit comments

Comments
 (0)