Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5.0 KiB
Community PR Readiness Check — teams and labels
Owner resolution, the GitHub-team → Linear-team → label mapping, and the Linear ticket label rules used when triaging.
Contents
- Identifying the owning team
- GitHub team → Linear team → GitHub label
- Linear ticket label rules
- Always-on label
- Type label (based on PR title prefix)
- Team-specific extra label
- Worked examples
Identifying the owning team
Use the canonical owners script at .github/scripts/owners.mjs. It parses .github/OWNERS with last-match-wins semantics and returns allocations sorted by file count with a share percentage. Using the script keeps this skill consistent with whatever CI uses.
- Write the PR's changed file paths (from the
fileslist) to a temp file, one per line:printf '%s\n' <path1> <path2> ... > /tmp/pr-<number>-files.txt - Run the script:
node .github/scripts/owners.mjs /tmp/pr-<number>-files.txt - The script prints JSON of the form:
Allocations are already sorted by
{ "totalFiles": 12, "allocations": [ { "team": "@n8n-io/ai", "fileCount": 10, "share": 83, "files": [...] }, { "team": "@n8n-io/catalysts", "fileCount": 2, "share": 17, "files": [...] } ] }fileCountdescending — take the first entry as the winning team. - Clean up:
rm /tmp/pr-<number>-files.txt. - Strip the
@n8n-io/prefix fromallocations[0].team— the GitHub team slug isnodes,iam,ai, etc. Ifallocationsis empty (no file matched any rule, which is possible only if.github/OWNERSlost its catch-all), fall back tocatalysts. - Map the GitHub team slug to its Linear team name and PR label using the table below. The
teamfield in the JSON output is the Linear team name. If the resolved GitHub team slug has no entry in the table, fall back toEngineering.
Sub-agent fallback: if node execution is denied by the sandbox, read .github/OWNERS directly and apply last-match-wins by hand. All the active rules fit on one screen.
GitHub team → Linear team → GitHub label
GitHub team (@n8n-io/…) |
Linear team | GitHub team label |
|---|---|---|
catalysts |
Catalysts | team:cats |
adore |
Adore | team:adore |
ai |
AI | team:ai |
nodes |
NODES | team:nodes |
design |
Design | team:design |
iam |
Identity & Access | team:identity |
ligo |
Lifecycle & Governance | team:lifecycle |
instance-ai |
instanceAI | team:instance-ai |
frontend |
Adore | team:adore |
qa-dx |
Developer Platform | team:qa-dx |
migrations-review |
Catalysts | team:cats |
The GitHub team label column is what gets applied to the PR after a successful Linear assignment (see reference/label-flow.md).
Linear ticket label rules
When calling the available Linear MCP issue-update tool to assign a ticket to a team, pass a labels array composed of three pieces:
Always-on label
GitHub— every community PR ticket carries this. In the Linear UI it renders assource > GitHub; thesourceprefix is a label-group parent, not part of the API name.
Type label (from PR title prefix)
| PR title type | Linear label |
|---|---|
feat |
feature |
fix |
bug |
anything else (perf, refactor, docs, ci, chore, build, test, revert) |
enhancement |
Pass the child label name only — Linear silently drops unknown labels, so don't include type > prefixes.
Team-specific extra label
| Destination team | Extra label |
|---|---|
| Catalysts | Community PR |
| NODES | community-pr |
| other teams | (no extra) |
Worked examples
featPR going to Catalysts:["GitHub", "feature", "Community PR"]fixPR going to NODES:["GitHub", "bug", "community-pr"]perfPR going to AI:["GitHub", "enhancement"]chorePR going to Lifecycle & Governance:["GitHub", "enhancement"]
Destination state
| Destination team | Linear state |
|---|---|
| NODES | Review |
| any other team | Triage |
NODES has a dedicated Review lane; every other team handles routing inside their own triage.