fix(labels): gitea_label_bootstrap hard-codes an upstream taxonomy that conflicts with the pvlb house set #8

Closed
opened 2026-10-23 17:34:50 +00:00 by dsh · 1 comment
Owner

Symptom

gitea_label_bootstrap advertises itself as "Idempotently sync the canonical label set into a repository". Run against a pvlb repo, it would create a second, incompatible taxonomy and still not create the labels the house rules require.

  • lib/label-bootstrap.js:6 hard-codes 34 labels from the upstream project: type/feature, type/tech-debt, type/refactor, type/docs, type/research, type/security, type/incident, priority/critical|high|medium|low, status/*, scope/*, risk/*, signal/*.
  • The pvlb house set (DSH Bootcamp, Issues and labels, 2026-10-23) is type/task + type/bug, area/host|backup|forgejo|dsh|security, priority/now|next|later, needs-operator.
  • The two sets share only type/bug. Bootstrap never creates type/task, area/dsh, priority/now, etc., and adds ~30 foreign labels to every repo it touches.

Observed 2026-10-23 on dsh-plugins/dsh-resend-mcp while adopting the label-at-creation policy. The repo had only 5 house labels (area/dsh, needs-operator, priority/later, priority/next, type/task); I created type/bug, priority/now, area/forgejo manually rather than run bootstrap.

The dry run also looked broken: it reported 0 label(s) planned/created even though the repo was missing most of CANONICAL_LABELS. Whether that is the preview path or the running build differing from this checkout, the preview cannot be trusted as-is.

Root cause

// lib/label-bootstrap.js:6
export const CANONICAL_LABELS = [
  { name: 'type/feature', ... },
  ...
]

One hard-coded upstream taxonomy, no notion of the deployment's house set, and the tool name/description invite agents to run it. The bootcamp says "if the repo lacks the set, create it" without warning against this tool, so the failure is reachable by following the docs.

Fix (pick one, document it)

  1. Replace CANONICAL_LABELS with the house taxonomy — this is a private deployment fork, and the house set is the one every repo here uses.
  2. Add a taxonomy: "house" | "upstream" argument (default house here) and keep both sets.
  3. Remove or rename the tool to make its upstream-only taxonomy explicit, and document the manual gitea_labels create snippet in the bootcamp instead.

Also make the dry run truthful: it must list the exact labels it would create, with a non-zero count when labels are missing.

Acceptance

  • On a pvlb repo, a bootstrap apply creates exactly type/task, type/bug, area/*, priority/now|next|later, needs-operator — no status/*, scope/*, risk/*, signal/* unless requested.
  • Dry run lists every label it would create, and reports 0 only when none are missing.
  • The tool description and the bootcamp say which taxonomy is used.
## Symptom `gitea_label_bootstrap` advertises itself as "Idempotently sync the canonical label set into a repository". Run against a pvlb repo, it would create a **second, incompatible taxonomy** and still not create the labels the house rules require. - `lib/label-bootstrap.js:6` hard-codes 34 labels from the upstream project: `type/feature`, `type/tech-debt`, `type/refactor`, `type/docs`, `type/research`, `type/security`, `type/incident`, `priority/critical|high|medium|low`, `status/*`, `scope/*`, `risk/*`, `signal/*`. - The pvlb house set (DSH Bootcamp, *Issues and labels*, 2026-10-23) is `type/task` + `type/bug`, `area/host|backup|forgejo|dsh|security`, `priority/now|next|later`, `needs-operator`. - The two sets share only `type/bug`. Bootstrap never creates `type/task`, `area/dsh`, `priority/now`, etc., and adds ~30 foreign labels to every repo it touches. Observed 2026-10-23 on `dsh-plugins/dsh-resend-mcp` while adopting the label-at-creation policy. The repo had only 5 house labels (`area/dsh`, `needs-operator`, `priority/later`, `priority/next`, `type/task`); I created `type/bug`, `priority/now`, `area/forgejo` manually rather than run bootstrap. The dry run also looked broken: it reported `0 label(s) planned/created` even though the repo was missing most of `CANONICAL_LABELS`. Whether that is the preview path or the running build differing from this checkout, the preview cannot be trusted as-is. ## Root cause ```js // lib/label-bootstrap.js:6 export const CANONICAL_LABELS = [ { name: 'type/feature', ... }, ... ] ``` One hard-coded upstream taxonomy, no notion of the deployment's house set, and the tool name/description invite agents to run it. The bootcamp says "if the repo lacks the set, create it" without warning against this tool, so the failure is reachable by following the docs. ## Fix (pick one, document it) 1. Replace `CANONICAL_LABELS` with the house taxonomy — this is a private deployment fork, and the house set is the one every repo here uses. 2. Add a `taxonomy: "house" | "upstream"` argument (default `house` here) and keep both sets. 3. Remove or rename the tool to make its upstream-only taxonomy explicit, and document the manual `gitea_labels create` snippet in the bootcamp instead. Also make the dry run truthful: it must list the exact labels it would create, with a non-zero count when labels are missing. ## Acceptance - [ ] On a pvlb repo, a bootstrap apply creates exactly `type/task`, `type/bug`, `area/*`, `priority/now|next|later`, `needs-operator` — no `status/*`, `scope/*`, `risk/*`, `signal/*` unless requested. - [ ] Dry run lists every label it would create, and reports 0 only when none are missing. - [ ] The tool description and the bootcamp say which taxonomy is used.
dsh closed this issue 2026-10-23 22:56:07 +00:00
Author
Owner

Fixed in 178a99f (PR #18).

gitea_label_bootstrap now defaults to the pvlb.dev house set — type/task, type/bug, area/host|backup|forgejo|dsh|security, priority/now|next|later, needs-operator (11 labels). The upstream 34-label set is still available as taxonomy: "upstream"; an unknown value fails instead of silently picking one. The dry run now returns missing/missingCount and the formatter lists every missing name; created is used only after an apply.

Live on ml-lab/tardits (had only type/bug):

  • dry run → 10 of 11 label(s) missing + the exact list;
  • apply → created those 10, no status/*/scope/*/risk/*/signal/*;
  • dry run again → 0 label(s) missing — repository already has all 11 labels;
  • gitea_labels list → exactly the 11 house labels (ids 47–57).

The house set was intentionally left on that lab repo. The in-repo agent guide (AGENTS.md) is updated to say bootstrap defaults to house; the external bootcamp wiki page was not edited — flag it if you want that changed too.

Tests: test/label-bootstrap.test.mjs; npm test 81/81.

Fixed in `178a99f` (PR #18). `gitea_label_bootstrap` now defaults to the pvlb.dev house set — `type/task`, `type/bug`, `area/host|backup|forgejo|dsh|security`, `priority/now|next|later`, `needs-operator` (11 labels). The upstream 34-label set is still available as `taxonomy: "upstream"`; an unknown value fails instead of silently picking one. The dry run now returns `missing`/`missingCount` and the formatter lists every missing name; `created` is used only after an apply. Live on `ml-lab/tardits` (had only `type/bug`): - dry run → `10 of 11 label(s) missing` + the exact list; - apply → created those 10, no `status/*`/`scope/*`/`risk/*`/`signal/*`; - dry run again → `0 label(s) missing — repository already has all 11 labels`; - `gitea_labels list` → exactly the 11 house labels (ids 47–57). The house set was intentionally left on that lab repo. The in-repo agent guide (`AGENTS.md`) is updated to say bootstrap defaults to house; the external bootcamp wiki page was not edited — flag it if you want that changed too. Tests: `test/label-bootstrap.test.mjs`; `npm test` 81/81.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
dsh-plugins/dsh-gitea#8
No description provided.