Skip to content

No gate bans the whole-set label PUT that #10703 removed - the verb can be reintroduced silently #10778

Description

@claude

Split out of #10703, which made both label writers in .github/workflows/pr-automation.yml additive. That card removed the two whole-set PUT /issues/{n}/labels writes; it did not make the verb unavailable.

The gap

Nothing mechanically stops a future workflow, action or agent from reintroducing a whole-set label write. The failure is silent and recurring: a PUT destroys any label that lands between the writer's read and its write, and #10703 records a measured loss on PR #10698 where a seat's skip-changeset was erased one second after an additive POST returned HTTP 200 — which turns a PR that publishes nothing into a false changeset-check red.

Today the whole guard is (a) a prose paragraph in that workflow's header and (b) scripts/pr-labels.mjs --self-test, which only constrains that one script. Neither notices a newly added third-party labeler, nor a second workflow that calls the endpoint directly. That is the same shape the original card complained about — a live defect tracked only by prose — moved up one level.

What a gate would assert

Over .github/workflows/** (and plausibly scripts/**):

  1. no PUT against /issues/{n}/labels, in any spelling — curl -X PUT, octokit/actions/github-script calling issues.setLabels, or gh api -X PUT .../labels;
  2. no uses: of an action known to write the whole set. codelytv/pr-size-labeler and actions/labeler were both verified to do so at their pinned versions, read out of source, in The PR-size labeler's whole-set PUT erases a seat-applied skip-changeset one second after an additive POST — measured loss, and the only tracker is prose in a closed card #10703;
  3. an allowlist entry requires a stated reason, so a deliberate exception is a recorded decision rather than an omission.

Why it was not done in that PR

A check:* gate needs an entry in the root package.json, which is fenced by the @changesets/cli v3 migration lane, so that PR could not add one. It wired the existing self-test into lint.yml by direct node scripts/... invocation instead, which covers the one script and nothing else. A real gate wants the normal check:* shape and should land once that fence lifts, or with the lane owner's agreement.

Filed unassigned, PM triage.


Generated by Claude Code


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions