chore(skills): route bug triage on AR-Blocks and priority, not severity

What this changes

The /bug-report skill and the project taxonomy now match epic &23325, which is the single source of truth for Artifact Registry bug triage.

Two label families decide everything. Both are required on a Closed Beta bug; a --general report names no release gate and carries a ~priority::* alone:

Label family Question it answers Values
~AR-Blocks::* Which release must this be fixed before? Closed-Beta, GA, Self-Managed, Dedicated
~priority::* In what order do we start it? priority::1 (missing implementation, or work crossing into another service or team — longer lead, start first), priority::2 (self-contained, fixable inside this codebase — quick, and can be picked up any time)

There is no third axis. Every ~severity::* value is retired, ~severity::1 included. No severity label is applied, required, routed on, or reported, and its absence is not a gap.

The launch gate is the blockers list itself: Closed Beta launches when the open ~AR-Blocks::Closed-Beta list is empty. ~AR-Blocks::Closed-Beta means the fix must land before the first customer onboards; ~AR-Blocks::GA is the label for work done during the beta, gating GA rather than the onboarding.

A defect that loses data, exposes data, or takes the service down carries no special label. It is ~AR-Blocks::Closed-Beta with ~priority::1, escalated directly to the DRI and in Slack. A security defect is still filed confidential and still carries ~bug::vulnerability.

The reversal in this MR

An earlier revision of this MR kept ~severity::1 as a Closed Beta halt gate and carried a section arguing for it. The epic's 2026-09-07 correction retired severity entirely, removed the halting view, and recorded that !2393 needed the same correction before merging. This MR applies it: the halt gate is gone from the skill, the reference rubrics, the template, and docs/dev/labels.md.

Why severity went

Severity had stopped discriminating on the queue a triager actually reads. On the 16 open ~AR-Blocks::Closed-Beta items, 8 of 8 ~priority::1 were S1-or-S2, and 6 of those 8 were S2 — severity and priority were saying the same thing, and neither was ordering the work.

Across all 58 direct children of &23325 the spread is wider (the epic records S3 21, S2 20, S4 9, S1 2, and 7 carrying none), so the collapse is specific to the Closed Beta queue. That is the queue this process exists to order, and ~AR-Blocks::* already records which release a defect gates.

~severity::1 went with the rest because "stop shipping until this closes" is now expressed by the gate rule rather than by a label: the open ~AR-Blocks::Closed-Beta list being non-empty is the statement that Closed Beta cannot launch.

Files

Path group LOC What
.claude/skills/bug-report/** 484 The skill: Phase 4 decides gate and priority and asks no halt question, Phase 7 reports no severity; the gate and priority rubric, required-label tables, worked examples, the body template, ar-bug-dupes printing each hit's priority instead of its severity, and ar-bug-create's new --require-scope
docs/dev/labels.md 4 The project-wide taxonomy: severity:: retired, priority:: qualified, and a new AR-Blocks:: row
docs/dev/agentic-development.md 10 The /bug-report entry described the skill as classifying severity
.claude/skills/review-branch/** 4 Its group-c reference told authors to set a severity::* label

All four path groups are needed for any to be correct. The skill's references/labels.md defers to docs/dev/labels.md on any label the two share, so landing the skill alone would leave it citing a taxonomy that still kept severity::1 alive. The two outside the skill were consumers the first sweep missed — a reviewer skill that would have asked every future author for a retired label, and the page a reader consults before invoking /bug-report.

docs/dev/labels.md gains an AR-Blocks:: row. An earlier revision of this description argued the opposite, on the grounds that references/labels.md claims the family "appears only here". That claim was the thing to change: docs/roadmap/closed-beta.md on main (b72a75644) names this MR and says docs/dev/labels.md "documents neither ~AR-Blocks::* nor ~priority::* … once it lands, the two agree and the pointer is good". Landing without the row would ship that merged sentence false. references/labels.md now lists AR-Blocks:: among the families the canonical file wins on, and its difference count drops from four to three.

Why the diff is past 500 reviewable LOC

502 across 11 files, past the threshold docs/dev/development-model.md asks about. Splitting would publish a contradiction at every intermediate commit: references/labels.md names docs/dev/labels.md its authority, template.md names references/labels.md its authority, and docs/roadmap/closed-beta.md on main already promises the taxonomy row this MR adds. Any subset leaves one of those three pointing at a file that contradicts it. The two consumer fixes outside the skill are 14 LOC together and are only correct once the scheme they describe exists.

Two things kept as they are, on purpose

  • references/severity.md keeps its filename although its subject is the release gate and the priority rubric. An earlier revision of this description said &23325 links to that path twice. It links once — description line 152; the path appears twice on that line only because the Markdown link repeats it, and all 50 notes on the epic carry none. So renaming is cheaper than that claim implied, and the reason it is not done here is different: &23325 is the source of truth and is out of bounds for edits by this MR, and a rename would 404 its one link the moment this merges. The filename explanation now sits at the top of the file, where a reader arriving from references/labels.md meets it, rather than at line 111 of 124 inside ## Severity labels are retired.
  • No mass relabelling. Measured on 2026-09-08 against the gitlab-org group, 161 issues carrying Category:Artifact Registry also carry a severity::* label, 106 of them open. Widening the retirement to severity::1 adds 4 issues to that set. Rewriting them would destroy the record of how they were triaged at the time for no operational gain, so the process treats them as history.

Review feedback applied

Automated review. The two "pickable up any time" nits are applied. The two "ambiguous it in until it closes" nits are moot — both lines were the halt-gate description, and both are deleted. references/template.md's "Labels to Apply" list regains the general-mode caveat on AR-Blocks::<gate>. The AppSec finding asking ar-bug-create to enforce bug::vulnerability → severity::1 is moot for the same reason: no severity check is added, and the bug::vulnerability → --confidential gate is unchanged and still enforced. Later rounds split the two SLA clocks and dropped the ~-prefix from label spans so all four reference files agree.

@radbatnag's review — twelve findings and one escalation. Each is answered in its own thread; the substantive ones:

  • The scheme contradicted itself, and this was the escalation. Priority is defined as start order by effort, and two rules assigned priority::1 on criticality — which reopens the conflation retiring severity was meant to close. Resolved by keeping the data-loss rule, which is &23325's own, and naming it in the definition as the single override the scheme carries; and by dropping the regression rule, which was this skill's invention. &23325 contains no occurrence of "regress". A recurrence is now a fact for the report body and for the gate, not a priority band.
  • The sweep had stopped at the skill directory. review-branch's group-c reference still told authors to set a severity::* label, and docs/dev/agentic-development.md still described the skill as classifying severity. Both fixed; neither is vendored.
  • "Both required on every bug" is false in --general mode, which names no release gate — and that sentence opened the first file Phase 4 reads, 170 lines before the carve-out. Qualified in severity.md and SKILL.md.
  • "Only these two priority values are in use" is false in the canonical taxonomy. All four exist as group labels and carry issues here: measured 2026-09-09, priority::1 18, ::2 41, ::3 19, ::4 17. Bug triage uses two; docs/dev/labels.md governs every issue, so it now says both things.
  • references/labels.md carried the retired Closed-Beta test — "a beta user cannot succeed without the fix" — while severity.md carried the corrected "before the first customer onboards". template.md names labels.md the authority, so the declared authority held the stale half. All three now agree.
  • The retirement never said what to do with a severity label already applied, and 82 of 97 open type::bug + Category:Artifact Registry issues carry one. It now says: leave it in place, do not read it, remove one added after the retirement. The "filed before that date" clause is gone — three task issues created 2026-09-08 already breached it.
  • ar-bug-create gains --require-scope. ar-bug-labels holds at-most-one-per-scope with a generic :: test; nothing held at-least-one, so a filing with no priority resolved cleanly and exited 0. That is observable in production of the process: 110 of 164 type::bug issues carry no priority::*. The flag is opt-in rather than keyed on type::bug, because which scopes are required depends on the mode and the caller is what knows it; Phase 6's documented command passes it the way it passes --parent.
  • no-priority is now the majority path in the duplicate list — 31 of 97 open bugs carry a priority label, against 82 carrying a severity one. Phase 3 now says what the sentinel means (the hit predates the scheme; absent information, not low priority), and two tests assert both branches.
  • Five prose pointers named a direction or a bare filename. Each now names its section, and severity.md's filename explanation moves to the top.

Verification

  • .claude/skills/bug-report/scripts/ar_bug_test.sh132 passed, 0 failed, up from 125. The seven new cases cover --require-scope (absent, present, duplicated, a second scope checked independently, and no-flag-no-check) and both branches of ar-bug-dupes' priority column.
  • No skill benchmark was run, and that is deliberate. docs/dev/conventions.md asks for one on any skill MR, but bug-report carries no evals/ suite — only mr-watch and write-readable-go do — so /skill-creator has nothing to score against. Recorded here so the omission reads as a decision rather than an oversight.
  • markdownlint-cli2 and vale pass on every changed Markdown file.
  • grep -rn 'severity::' --include='*.md' --include='*.sh' . over the whole repository returns only the retirement statements themselves and docs/plans/2026-09-01-package-id-fk-check-indexes.md, which quotes a historical severity::4 and says the plan changes no label. Widening the grep past the skill directory is what surfaced the two missed consumers.
  • The difference count in references/labels.md is now three, re-checked member by member after adding the AR-Blocks:: row: the bug:: subtypes functional, transient and ux; the frontend/backend requirement; and regression. AR-Blocks:: moved from the differences to the overlaps, and no new difference appeared.
  • shellcheck on ar-bug-create and ar_bug_test.sh reports only the pre-existing SC1091 for the lib.sh source.
  • The ar-bug-labels usage example was re-run live on this branch: gid://gitlab/GroupLabel/3857523 priority::2.

Related to gitlab-org#23325

Edited by Jaime Martinez

Merge request reports

Loading
Loading