docs(labels): record sync scope and define an approved unknown-label sweep - #528
Merged
Conversation
The label runbook did not state which repositories canonical label sync targets. `labels-sync.rb --all-repos` audits every repository the token can see, which is wider than the sync scope, so private and fork repositories report as drift indefinitely and inflate org-wide totals. A 2026-08-19 audit measured 93 repositories, of which 86 are active, public, and non-fork. The remaining 7 accounted for 215 missing canonical labels and 116 legacy labels, all of it expected rather than regression. Record the scope, name the exclusions and the reason for each, and state that a repository entering active public non-fork status enters scope at that point.
The runbook prohibited bulk deletion of unknown labels outright, but a maintainer-approved sweep on 2026-08-19 removed 1,390 unused unknown definitions across 86 repositories. Guidance and practice now disagree, and an absolute rule that has already been overridden once gives no guidance on how to do it safely the next time. Keep the prohibition as the default and add the conditions an approved sweep must meet: live usage measured from the issues API rather than the lagging search index, deletion limited to zero-item definitions, preservation of configuration-referenced labels verified by reading labeler and stale workflows, a restorable archive, a verified pilot, per-repository batching, and a post-run re-derivation of every survivor. State that sync_policy.delete_unknown_labels stays false, so an approved one-off never becomes the default.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two gaps in
runbooks/labels.mdsurfaced by the 2026-08-19 label audit.1. Sync scope was never written down
labels-sync.rb --all-reposaudits every repository the token can see, which is wider than what canonical sync actually targets. The result is that private and fork repositories report as drift forever and inflate org-wide totals.Measured on 2026-08-19: 93 repositories audited, 86 active/public/non-fork. The other 7 accounted for 215 missing canonical labels and 116 legacy labels, all of it out of scope rather than regression.
This records the scope, names each exclusion with its reason, and states that a repository entering active public non-fork status enters scope at that point.
2. The bulk-delete prohibition had already been overridden
The runbook said "Do not delete unknown labels in bulk" with no exception path. A maintainer-approved sweep on 2026-08-19 deleted 1,390 unused unknown definitions across the 86 in-scope repositories, taking unknown labels from 1,483 to 93.
Rather than weaken the rule to match what happened, this keeps the prohibition as the default and documents the conditions an approved sweep must meet, so the next one is done safely instead of improvised:
issues?state=all, never the search API, whose index lagged the May bulk changes badly enough to report 52 phantom items for a label attached to nothing;labeler.ymland stale/lock workflow inputs;It also states that
sync_policy.delete_unknown_labelsstaysfalse, so an approved one-off never becomes the default.Why condition 4 is load-bearing
Deleting a configuration-referenced label does not fail loudly.
actions/labelerapplies labels through the issues API, which creates a missing label rather than erroring, so the sweep quietly undoes itself on the next matching pull request. That is not hypothetical: it is whyenhancement ✨reappeared inz-shell/ziafter #467 deleted it. Tracked separately in #527.Verification
Documentation only, no executable change. Scope and figures were verified against live audit output rather than the earlier report; the sweep result was re-audited org-wide with every one of the 93 survivors re-derived as in-use or configuration-referenced, and zero unjustified leftovers.
Related: #467, #524, #527