Issue Labels โ Strong Suggestion
Why this exists: at one point we had 88 labels. That's worse than zero โ labels are only useful if they mean the same thing every time, and 88 labels does not. This document is the strong suggestion for what labels we use on humanity-org/humanwork.
Status (2026-06-03): Labels remain a strong suggestion โ the central taxonomy is the shared reference for humans and agents, but no CI workflow enforces it. PR authors / agents should match this set; mismatches are reviewed by humans, not stripped by bots. The label-enforcement bot was removed permanently in commit
e6b93068(it was causing too many problems on legitimate human-set labels). The LLM-classifier described further down is preserved for reference but is not wired into any active workflow.
Total label count: 34. Everything you'd want to know about an issue (kind / where / urgency / state / who-owns-it / blockers) fits in ~34 labels. If you find yourself wanting a 35th, the answer is almost always "put it in the issue title or body, not a label."
To add a new label to the strong-suggestion set, edit
scripts/labels/canonical.pyand open a PR โ don't create one-off labels in the GitHub UI. The bot is gone but the central list is still the shared reference.
TL;DR โ the labelsโ
| Namespace | Count | What it answers |
|---|---|---|
type:* | 3 | What kind of work is this? (bug / feature / epic) |
area:* | 4 | Which part of the system does it touch? (backend / frontend / agent / infra) |
needs:decision | 1 | Blocked on a decision |
priority:p0..p3 | 4 | How urgent? (strong suggestion) |
status:* | 7 | Where in the workflow? (strong suggestion) |
role:* | 5 | Which agent owns the next move? (strong suggestion) |
harness:* | 5 | Harness markers (managed / budget-exceeded / evidence-retry / security-sweep / deep-review) |
| GitHub defaults | 5 | good first issue, help wanted, duplicate, invalid, wontfix |
A typical, well-labeled issue:
type:feature area:backend priority:p1 status:ready role:eng
You almost never need more than that.
type:* โ kind of work (3)โ
Choose exactly one of these per issue. PRs don't need a type:* (the PR title prefix carries it).
| Label | Use when |
|---|---|
type:bug | Something broken or behaving wrong in a shipped behavior |
type:feature | New capability, enhancement, refactor, tech-debt, or docs โ anything that isn't a bug. (We don't split chore from feature โ the title tells the story.) |
type:epic | Workstream root โ parent of many child tasks |
Merged into here: , bug, enhancement, type:chore, type:docs. Questions belong in GitHub Discussions, not as labels.type:question
area:* โ what part of the system (4)โ
Choose one or more. Most issues touch one area; full-stack issues touch two.
| Label | Scope (intentionally wide) |
|---|---|
area:backend | NestJS api/ โ everything server-side: controllers, services, guards, billing, channels (Slack/Email/etc.), RAG pipeline, security, database/migrations, third-party integrations, ops APIs |
area:frontend | Next.js frontend/ โ everything client-side: /client/*, /workspace/*, /ops/*, UX, accessibility |
area:agent | FastAPI agent/ Python service โ prompt config, tool calling, Specialist personas, R2 manifest sync |
area:infra | Kubernetes, Railway, CI/CD, GitHub Actions, build tooling, test infrastructure, branch protection |
Why we collapsed 16 areas into 4. Most of the legacy area:* labels (billing, channels, rag, onboarding, security, database, integrations, ops, expert-workspace, client-portal, specialists, testing) had fewer than 15 issues each, and the issue title always made the sub-area obvious ("billing: prorate Specialist rate change", "rag: ingestion retry"). One filterable dashboard with 4 buckets beats 16 narrow filters nobody remembers exist.
Where does X live?โ
| Sub-area | Lives under |
|---|---|
| Billing / Lago / Stripe | area:backend |
| Channels (Slack/Email/Telegram/WhatsApp) | area:backend (server) + area:frontend if there's a UI |
| RAG / KB pipeline / data hygiene | area:backend |
| Onboarding flow | area:backend + area:frontend |
| Security / RLS / auth | area:backend |
| Database / migrations / TypeORM | area:backend |
| Third-party integrations (Nango, Tavus) | area:backend |
/ops/* (AM / SuperAdmin) | area:frontend (it's a route surface) |
/workspace/* (Expert) | area:frontend |
/client/* (Client portal) | area:frontend |
| Specialist personas | area:agent (logic) + area:frontend (Tavus ops UI (/ops/tavus/*)) |
| Tests / CI / e2e / perf | area:infra |
needs:decision (1)โ
Use this when an issue can't move forward without an architectural or product decision. One label, not three. There used to be needs:human and needs:triage; both were redundant with status:needs-human and status:ready (without role:eng), so they're gone.
| Label | Means |
|---|---|
needs:decision | Blocked on a decision someone needs to make |
priority:p0..p3 โ urgency (strong suggestion, 4)โ
Set by the PM agent during scoping. Exactly one per issue.
| Label | Means |
|---|---|
priority:p0 | Drop everything. Launch blocker / production incident. |
priority:p1 | High โ needed before 10 customers, or current sprint must-have. |
priority:p2 | Normal โ current quarter, default for most issues. |
priority:p3 | Backlog โ nice-to-have, deferred. |
Merged in: , P0/P1/P2/P3 (โ mvp-blockerpriority:p0), /high-priority/medium-priority.low-priority
Strong suggestion โ see
agent-team-harness/harness/labels.py. Humans set/change priority freely. The label-enforcement bot was removed 2026-06-03 (e6b93068) so non-suggested priorities are no longer auto-stripped.
status:* โ workflow state (strong suggestion, 7)โ
Driven by the agent-team-harness FSM. Don't set by hand unless the transition is valid.
| Label | Means |
|---|---|
status:ready | Scoped and ready for an agent to pick up. Also the entry state for new issues: a new issue gets status:ready + role:pm so the PM agent scopes it next tick. (The legacy status:triage was retired โ role:pm is enough to disambiguate "needs scoping" from "ready for eng".) |
status:wip | Agent actively working |
status:review | Awaiting code review |
status:test | Awaiting black-box testing |
status:blocked | Blocked on another issue/agent |
status:needs-human | Needs human intervention |
status:done | Completed |
Valid transitions: ready โ wip โ {review, test, done, needs-human}; review โ {test, ready, done, needs-human}; etc. โ see _VALID_TRANSITIONS in the harness source.
role:* โ agent ownership (strong suggestion, 5)โ
Which agent role owns the next move. Set by the harness dispatcher. Don't edit by hand.
| Label | Means |
|---|---|
role:pm | PM agent โ scoping / triage / decomposition. |
role:eng | Eng agent โ implementation. |
role:test | Test agent โ black-box / e2e verification. |
role:review | Review agent โ code review. |
role:security | Security agent โ security sweep / IDOR / auth posture (added per #1497 / #1505 / #2026). |
role:contract | Contract-validation agent owns next action (AC testability gate before Eng). |
harness:* โ harness markers (strong suggestion, 5)โ
| Label | Means |
|---|---|
harness:managed | Issue is under harness control. Without this, the dispatcher ignores the issue. |
harness:budget-exceeded | Agent ran out of token / wall-clock budget โ needs human review. |
harness:evidence-retry | Evidence collection step failed; harness retried (per #1497). |
harness:security-sweep | Issue is part of a coordinated security sweep (per #1505 / #2026). |
harness:deep-review | Issue requires deep-review treatment (per #2026) โ extended review budget. |
harness:trivial | Skip contract-validation step; route PM โ Eng directly. |
harness:circuit-broken | CI failing too many times โ needs human to fix and re-queue. |
harness:debate-mode | Run two implementers + judge arbitration instead of single-implementer flow. |
Retired:
bounce:0..3. The retry counter is now embedded as<!-- harness:bounce=N -->in the most recent agent comment. Labels are bad storage for a 0..3 integer that changes every tick.
GitHub default labels (kept, 5)โ
| Label | When |
|---|---|
good first issue | Approachable for new contributors |
help wanted | Open call for outside help |
duplicate | Already exists โ close after linking the original |
invalid | Misfiled or not actionable as written |
wontfix | Acknowledged but explicitly declined |
Migration historyโ
| Date | Cut | Why |
|---|---|---|
| 2026-05-24 (pass 1) | 88 โ 52 | Folded workstream:* (duplicate of area:*), P0..P3 into priority:p0..p3, bug/enhancement/docs into type:*, mvp-blocker into priority:p0. |
| 2026-05-24 (pass 2) | 52 โ 30 | Collapsed 16 fine-grained area:* labels into 4 wide buckets. Cut type:chore/type:docs/type:question (folded into type:feature). Cut needs:human/needs:triage (duplicates of status:*). Cut harness status:triage (folded into status:ready + role:pm) and bounce:0..3 (moved to comment marker). |
| 2026-05-25 (label-hygiene sweep) | 36 โ 30 (repo); 95 open issues curated | Deleted 6 stale repo labels still present in the GitHub UI but not on the canonical list: P1, backend, frontend, infrastructure, bug, bounce:0. Migrated their last 4 user-issues to canonical equivalents (area:backend, area:frontend, area:infra, type:bug). Resolved 1 multi-priority conflict (#558 dropped priority:p2). Collapsed 12 epics with dual type:epic + type:feature โ kept only type:epic. Added priority:p2 to 10 Workstream epics (#611โ#620). Added status:ready to 51 issues missing a status. Added type:feature to 38 issues missing a type. After the sweep: every open issue (95) has exactly 1 priority:*, 1 type:*, 1 status:* per the rules at the top of this doc. |
| 2026-06-03 (label-bot removal + harness/role extension) | 30 โ 34 (strong suggestion); enforcement removed | Added harness:evidence-retry (#1497), role:security (#1505), harness:security-sweep (#1505 / #2026), harness:deep-review (#2026). Same day, commit e6b93068 deleted the label-enforcement workflow (.github/workflows/label-enforcement.yml). Labels remain a strong suggestion; CI no longer auto-strips. |
Adding a new labelโ
Open a PR editing scripts/labels/canonical.py. In the PR description, justify:
- Which existing labels did you consider, and why don't they fit?
- Will this label apply to at least 20 issues in the next quarter? (Bar deliberately set high โ small label sets are the whole point.)
- Which namespace does it belong in?
If the answer to (2) is "no", you probably want a sub-task, a project-board column, or just the issue title โ not a new label.
Historical: prior enforcement (removed 2026-06-03)โ
Before commit e6b93068, .github/workflows/label-enforcement.yml ran on issues and pull_request labeled / opened / edited events. It:
- Read
scripts/labels/canonical.py. - Removed any label not in the canonical set via the REST API.
- Posted a sticky comment linking back to this page.
The workflow also called scripts/labels/classify.py (OpenRouter โ Haiku 4.5 โ gpt-4o-mini fallback) to fill in missing required slots from the just-stripped labels, confidence-gated (default โฅ0.7).
Why it was removed: the bot's auto-strip + sticky-comment loop was generating churn on legitimate human-set labels and the LLM-classifier had a low signal-to-noise ratio in practice. The taxonomy still serves as the shared reference; enforcement is now author-discipline rather than CI.
The classifier script (scripts/labels/classify.py) and scripts/labels/canonical.py are preserved in-tree for reference and ad-hoc use, but no workflow currently invokes them.