Files
holocron/plugins/gitea/.apm/skills/gitea-labels-milestones/references/label-inference.md
Defame1297 8680adf4c0 fix(gitea): make gitea-releases executable and correct misleading domain claims
gitea-releases was the weakest skill in the plugin: no allowed-tools, no
owner/repo resolution, and a checkbox list where a dispatch table belongs, so
an agent reaching it had to guess both its permissions and its inputs. The
id-vs-tag_name trap — deleting by tag name where the API wants the numeric id —
is restored as an explicit Gotcha because it destroys the wrong release
silently.

Elsewhere the `exclusive` flag was documented on the wrong side of the
read/write split, and label data from one instance was presented as though it
were universal, which invites an agent to assume a taxonomy that does not
exist on the target repo. rename_branch was missing from the branch surface.
Reference prose and fences are cleaned up in passing.
2026-08-31 08:01:33 +00:00

4.3 KiB

topic, source_keys
topic source_keys
label-inference
context7-websites-gitea
gitea-mcp-repo

Label inference guide

Maps context-pattern signals from conversation content (an issue being drafted, a bug report, a PR description) to this repo's Kind/* / Priority/* / Status/* label taxonomy. Used by gitea-issues and gitea-prs before creating or updating an issue/PR, and directly when the user asks to label something without naming exact labels.

Branching on exclusivity

references/labels.md owns the exclusivity rule and the read-versus-write asymmetry behind it. Read it there rather than assuming a scope's behaviour from its name. Inference needs only the branch: carry each candidate label's own exclusive value forward from the resolution call and act on it.

  • exclusive: true — the server drops the sibling on write. Add the label and let it; do not pre-remove the label already there, and do not compute a replacement set client-side. Inferring Priority/High onto an issue carrying Priority/Medium needs no special handling.
  • exclusive: false — add alongside, never replace. Stripping a co-existing label in the same scope destroys a valid one: an issue can legitimately carry Kind/Bug and Kind/Security at once.

This skill enforces no client-side exclusivity convention of its own.

Signal → label mapping

Kind/* (what kind of work this is):

Signal in context Label
Bug report, error, crash, unexpected behavior, "broken", "doesn't work" Kind/Bug
New capability, "add support for", net-new functionality Kind/Feature
Improvement to existing behavior, "make X better", refactor with behavior change Kind/Enhancement
Docs-only change, README/comment/guide updates Kind/Documentation
Vulnerability, credential exposure, injection risk, auth bypass Kind/Security
Test coverage, "add tests for X", a missing or flaky test, a test-only change Kind/Testing

Priority/* (urgency):

Signal in context Label
"blocking", "critical", "urgent", production-down Priority/Critical
"soon", "high priority", "should do this sprint" Priority/High
"low priority", "nice to have", "whenever", explicitly deferred Priority/Low
No urgency signal present Priority/Medium (default)

Status/* (workflow state):

Signal in context Label
Explicit statement that the work is blocked on something else Status/Blocked

The label names in all three tables are the taxonomy this guide was written against; none of them is guaranteed to exist on the target repo. Step 2 below resolves every inferred name against the live label set, and a name that does not resolve is reported rather than substituted.

Procedure

  1. Read the conversation context (issue/PR title, body, or the triggering discussion) for the signals above.
  2. Call label_read method: "list_repo_labels" (see references/labels.md) to get the current label set with IDs and each label's exclusive value — inference must never guess an ID, only a name, then resolve it. Both pools can apply to one issue, so for any inferred name absent from the repo pool, also call label_read method: "list_org_labels" with org set to the repo's owner before treating it as unresolved. Read that call's failure text: a required=[read:organization] scope error means the org pool was never queried — report the missing token scope rather than reporting the label unresolved. Only a not-found response means there is no org pool and the name is genuinely absent.
  3. Match inferred label names against the resolved list (case-insensitive) and carry each match's exclusive value forward: true means the server replaces the sibling on write, false means the label is added alongside whatever is already applied (see above).
  4. Low-confidence inference omits the label. If no signal confidently maps to a Kind/* value, do not guess — omit Kind/* entirely rather than default to one. Priority/Medium is the one exception: it's the explicit default when no urgency signal is present, not a guess.
  5. Hand the resolved IDs, each with its exclusive value, to the caller's issue_write/ pull_request_write call — this skill does not apply labels to an issue or PR itself.