Linear Escalation Triage
Overview
Workflow for Linear tickets assigned to you, in two modes:
- Oncall mode — weekly rotation; proactively handle the queue
- Project mode — outside oncall; work a specific Linear-tracked ticket
Both modes share the same per-ticket protocol. They differ in entry conditions and exit conditions.
Core principle: sweep before you dive. Without a sweep, whatever's loudest wins — which is how P1s sit in Triage for weeks before someone notices.
Required tools
mcp__linear-server__list_issues — queue sweep
mcp__linear-server__get_issue / list_comments — pull context
mcp__linear-server__list_issue_statuses — enumerate your team's status names (don't assume)
mcp__linear-server__save_comment / save_issue — post reply, transition status
Bash(gh:*) — pull linked external issues, search PR history
Optional tools (graceful degradation)
mcp__rsry__* — bead-based record-keeping (recommended; if unavailable, keep notes locally and skip the Record step)
WebFetch — for fetching external runbooks / docs
- Knowledge-base search (Glean / equivalent) — for prior-art lookups
When to Use
- Start of weekly oncall rotation → full sweep
- Specific escalation comes in (Slack ping, external ping, ticket assignment) → per-ticket protocol
- Aged P1/P2 in
Triage > 7 days
- Stale-Todo cleanup pass
When NOT to Use
- One-off investigation with no Linear ticket → generic investigation
- Code work where the ticket is well-defined and the implementation is clear (no triage needed)
- Internal-only design work without a customer-facing escalation → use a planning skill instead
Setup (one-time per user)
- Create a triage repo:
mkdir ~/triage && cd ~/triage && git init
- Enable rsry:
rsry enable ~/triage
- Discover your Linear team's status names: call
mcp__linear-server__list_issue_statuses with team: <your-team-name> and note which name maps to each type (triage, started, completed, etc.). The skill assumes generic names below; substitute your team's actual names when you use it.
- Note your canonical doc URLs (public docs, internal runbooks) somewhere persistent — memory entries or a local config file.
Oncall-mode sweep
Start of week
list_issues assignee:me (no status filter, all open)
- Flag in this order:
- P1/P2 in
Triage > 7 days — top of stack
- P1+ in
Todo not yet started — second
- Anything in
Triage > 30 days — "should we still own this?"
- Stale-Todo audit: for each
Todo > 30 days, ask "did the work happen elsewhere?" Cross-check git log, knowledge-base search, and PR history on related repos for keywords in the ticket title. Close stale tickets aggressively — they pollute the queue and hide real signal.
- Open a bead per actionable ticket in your triage repo (template below). Set
**Mode:** oncall in body.
End of week
Write a handoff bead: tickets touched, status of each, what the next oncall should pick up first. Title: oncall-handoff-YYYY-WW. Future you (or the next rotation) reads this before doing their own sweep.
Project mode
Skip the sweep — you're on a specific ticket. Jump straight to the per-ticket protocol. Set **Mode:** project in any bead you open.
Per-ticket protocol (both modes)
- Pull context: Linear body + comments, linked external issue, linked support ticket, stakeholder identifier, escalator name + date if relevant.
- Hypothesize first: from symptoms alone, write 1-3 candidate root causes before touching code. Forces a falsifiable claim and prevents jumping to "obvious" answers that turn out wrong.
- Verify in codebase: grep for exact error strings (not paraphrases). Dispatch a search agent for cross-references if the symptom is non-obvious. Rank file:line citations.
- Search the knowledge base with the exact error string, quoted. Look for prior runbooks, support tickets, standing customer-issue trails.
- Cross-check canonical docs: maintained runbooks, public docs, role/policy definitions. Identify the source of truth before drafting the reply.
- Draft reply in two tones:
- Customer-facing: collaborative ("path forward" not "you need to"); link only to public canonical docs.
- Internal: tight citation chain; link to all prior internal cases for next-time reuse.
- Show drafts before posting — never post on Linear without explicit approval. Customer comms is irreversible.
- Post + transition:
- Top-level comment on the Linear ticket (not a reply unless thread shape demands it)
- Transition status appropriately (see status semantics below)
- Never touch the synced external issue — Linear handles linkback via status type
- Record a bead in your triage repo (template below).
- Document hiccups: anything the skill didn't help with → separate bead titled
skill-refactor: <thing>. These accumulate as the refactor backlog.
Linear status semantics
Linear statuses have types (triage, unstarted, started, completed, canceled, backlog) and team-specific names. The type determines synced-external-issue behavior — only completed closes linked external issues.
| Type |
Common names |
Sync effect |
| triage |
Triage |
none |
| unstarted |
Todo, Backlog |
none |
| started |
In Progress, In Review, Blocked |
none |
| completed |
Done |
closes linked external issue |
| canceled |
Canceled, Duplicate |
depends on team config |
For "awaiting customer" — most teams use Blocked (type=started, no sync close). Confirm your team's convention via list_issue_statuses rather than assuming a name exists.
Bead template
**Linear:** <linear-url>
**External issue:** <gh-url-if-linked>
**Support ticket:** <support-url-if-linked>
**Stakeholder:** <identifier>
**Mode:** oncall | project
**Filed by:** <person> on <date>
**Priority:** P1/P2/P3
**Linear status:** <state>
## Symptom
<paste verbatim error in code block>
## Root cause
<one paragraph or "TBD">
## Action taken (<date>)
- <what you did>
- <what you posted>
- <status transition>
## Awaiting
<what unblocks closing this bead>
## Provenance
- Runbook: <url>
- Public docs: <url>
- Prior cases: <links>
Create via:
mcp__rsry__rsry_bead_create
repo_path: <your triage repo path>
issue_type: research
priority: 1 (P1) / 2 (P2) / 3 (P3+)
Discovery via rsry (when available)
rsry_bead_search query=<ticket-id> — look up specific ticket history
rsry_list_beads --status=open — current in-flight queue
rsry_list_beads --status=blocked — awaiting external action
- Title prefix
oncall-handoff- — past oncall handoffs
Counter-rules (failure modes)
| Don't |
Why |
| Lead with "prior art" framing in customer-facing tickets |
Reads as defensive / blame-shaped |
| Dismiss workarounds without reading the canonical runbook |
Partial workarounds often satisfy stated success criteria |
| Post on Linear without explicit approval |
Customer comms is irreversible — show drafts |
| Cite people in design talk ("we agreed", "X said") |
Anchor to functional artifacts (PRD, code, docs), not personal attributions |
| Touch external issues when Linear owns the lifecycle |
The Linear ↔ external sync handles state via type:completed |
| Conflate diagnosis confidence with action framing |
"Am I right?" and "should the customer do X?" are different questions |
Red flags — STOP
- "I'll just post it real quick" → STOP. Show the draft.
- "Customer obviously needs to..." → STOP. Re-check the canonical doc.
- "This is a [product] bug" → STOP. Correctness vs UX? Different routing.
- "Workaround is bad, don't recommend" → STOP. Re-read what the workaround enables before recommending against it.
- "Beads say we already did X" → STOP. Verify against current state (
git log, PR list, ticket states) before recommending from stale memory.
Common mistakes
- Assuming a status name exists: always run
list_issue_statuses for your team rather than assuming names like "Awaiting Customer" exist.
- Conflating Linear and external lifecycles: only
completed-type status closes linked external issues. Blocked keeps them open.
- Sweeping without a notebook: a bead-per-ticket is the discipline that lets you walk away mid-sweep and resume cleanly.
- Recommending from stale bead memory: beads are notes frozen in time. Verify file paths, PR existence, and ticket states against current reality before acting on them.
1---2name: linear-escalation-triage3description: Use for Linear tickets assigned to you — oncall queue sweeps, aged P1/P2 escalations in Triage > 7 days, stale Todos needing cleanup, or an external escalation (Slack/support) surfacing a ticket needing a triaged reply.4---56# Linear Escalation Triage78## Overview910Workflow for Linear tickets assigned to you, in two modes:1112- **Oncall mode** — weekly rotation; proactively handle the queue13- **Project mode** — outside oncall; work a specific Linear-tracked ticket1415Both modes share the same per-ticket protocol. They differ in *entry conditions* and *exit conditions*.1617**Core principle:** sweep before you dive. Without a sweep, whatever's loudest wins — which is how P1s sit in `Triage` for weeks before someone notices.1819## Required tools2021- `mcp__linear-server__list_issues` — queue sweep22- `mcp__linear-server__get_issue` / `list_comments` — pull context23- `mcp__linear-server__list_issue_statuses` — enumerate your team's status names (don't assume)24- `mcp__linear-server__save_comment` / `save_issue` — post reply, transition status25- `Bash(gh:*)` — pull linked external issues, search PR history2627## Optional tools (graceful degradation)2829- `mcp__rsry__*` — bead-based record-keeping (recommended; if unavailable, keep notes locally and skip the `Record` step)30- `WebFetch` — for fetching external runbooks / docs31- Knowledge-base search (Glean / equivalent) — for prior-art lookups3233## When to Use3435- Start of weekly oncall rotation → full sweep36- Specific escalation comes in (Slack ping, external ping, ticket assignment) → per-ticket protocol37- Aged P1/P2 in `Triage` > 7 days38- Stale-Todo cleanup pass3940## When NOT to Use4142- One-off investigation with no Linear ticket → generic investigation43- Code work where the ticket is well-defined and the implementation is clear (no triage needed)44- Internal-only design work without a customer-facing escalation → use a planning skill instead4546## Setup (one-time per user)47481. Create a triage repo: `mkdir ~/triage && cd ~/triage && git init`492. Enable rsry: `rsry enable ~/triage`503. Discover your Linear team's status names: call `mcp__linear-server__list_issue_statuses` with `team: <your-team-name>` and note which name maps to each `type` (`triage`, `started`, `completed`, etc.). The skill assumes generic names below; substitute your team's actual names when you use it.514. Note your canonical doc URLs (public docs, internal runbooks) somewhere persistent — memory entries or a local config file.5253## Oncall-mode sweep5455### Start of week56571. `list_issues assignee:me` (no status filter, all open)582. Flag in this order:59 - **P1/P2 in `Triage` > 7 days** — top of stack60 - **P1+ in `Todo` not yet started** — second61 - **Anything in `Triage` > 30 days** — "should we still own this?"623. **Stale-Todo audit**: for each `Todo` > 30 days, ask *"did the work happen elsewhere?"* Cross-check `git log`, knowledge-base search, and PR history on related repos for keywords in the ticket title. Close stale tickets aggressively — they pollute the queue and hide real signal.634. Open a bead per actionable ticket in your triage repo (template below). Set `**Mode:** oncall` in body.6465### End of week6667Write a **handoff bead**: tickets touched, status of each, what the next oncall should pick up first. Title: `oncall-handoff-YYYY-WW`. Future you (or the next rotation) reads this before doing their own sweep.6869## Project mode7071Skip the sweep — you're on a specific ticket. Jump straight to the per-ticket protocol. Set `**Mode:** project` in any bead you open.7273## Per-ticket protocol (both modes)74751. **Pull context**: Linear body + comments, linked external issue, linked support ticket, stakeholder identifier, escalator name + date if relevant.762. **Hypothesize first**: from symptoms alone, write 1-3 candidate root causes *before* touching code. Forces a falsifiable claim and prevents jumping to "obvious" answers that turn out wrong.773. **Verify in codebase**: grep for *exact* error strings (not paraphrases). Dispatch a search agent for cross-references if the symptom is non-obvious. Rank file:line citations.784. **Search the knowledge base** with the exact error string, quoted. Look for prior runbooks, support tickets, standing customer-issue trails.795. **Cross-check canonical docs**: maintained runbooks, public docs, role/policy definitions. Identify the source of truth *before* drafting the reply.806. **Draft reply in two tones**:81 - **Customer-facing**: collaborative ("path forward" not "you need to"); link only to public canonical docs.82 - **Internal**: tight citation chain; link to all prior internal cases for next-time reuse.837. **Show drafts before posting** — never post on Linear without explicit approval. Customer comms is irreversible.848. **Post + transition**:85 - Top-level comment on the Linear ticket (not a reply unless thread shape demands it)86 - Transition status appropriately (see status semantics below)87 - **Never touch the synced external issue** — Linear handles linkback via status type889. **Record a bead** in your triage repo (template below).8910. **Document hiccups**: anything the skill didn't help with → separate bead titled `skill-refactor: <thing>`. These accumulate as the refactor backlog.9091## Linear status semantics9293Linear statuses have *types* (`triage`, `unstarted`, `started`, `completed`, `canceled`, `backlog`) and team-specific *names*. The type determines synced-external-issue behavior — only `completed` closes linked external issues.9495| Type | Common names | Sync effect |96|---|---|---|97| triage | `Triage` | none |98| unstarted | `Todo`, `Backlog` | none |99| started | `In Progress`, `In Review`, `Blocked` | none |100| completed | `Done` | **closes linked external issue** |101| canceled | `Canceled`, `Duplicate` | depends on team config |102103For "awaiting customer" — most teams use `Blocked` (type=`started`, no sync close). Confirm your team's convention via `list_issue_statuses` rather than assuming a name exists.104105## Bead template106107```108**Linear:** <linear-url>109**External issue:** <gh-url-if-linked>110**Support ticket:** <support-url-if-linked>111**Stakeholder:** <identifier>112**Mode:** oncall | project113**Filed by:** <person> on <date>114**Priority:** P1/P2/P3115**Linear status:** <state>116117## Symptom118<paste verbatim error in code block>119120## Root cause121<one paragraph or "TBD">122123## Action taken (<date>)124- <what you did>125- <what you posted>126- <status transition>127128## Awaiting129<what unblocks closing this bead>130131## Provenance132- Runbook: <url>133- Public docs: <url>134- Prior cases: <links>135```136137Create via:138139```140mcp__rsry__rsry_bead_create141 repo_path: <your triage repo path>142 issue_type: research143 priority: 1 (P1) / 2 (P2) / 3 (P3+)144```145146## Discovery via rsry (when available)147148- `rsry_bead_search query=<ticket-id>` — look up specific ticket history149- `rsry_list_beads --status=open` — current in-flight queue150- `rsry_list_beads --status=blocked` — awaiting external action151- Title prefix `oncall-handoff-` — past oncall handoffs152153## Counter-rules (failure modes)154155| Don't | Why |156|---|---|157| Lead with "prior art" framing in customer-facing tickets | Reads as defensive / blame-shaped |158| Dismiss workarounds without reading the canonical runbook | Partial workarounds often satisfy stated success criteria |159| Post on Linear without explicit approval | Customer comms is irreversible — show drafts |160| Cite people in design talk ("we agreed", "X said") | Anchor to functional artifacts (PRD, code, docs), not personal attributions |161| Touch external issues when Linear owns the lifecycle | The Linear ↔ external sync handles state via `type:completed` |162| Conflate diagnosis confidence with action framing | "Am I right?" and "should the customer do X?" are different questions |163164## Red flags — STOP165166- "I'll just post it real quick" → STOP. Show the draft.167- "Customer obviously needs to..." → STOP. Re-check the canonical doc.168- "This is a [product] bug" → STOP. Correctness vs UX? Different routing.169- "Workaround is bad, don't recommend" → STOP. Re-read what the workaround enables before recommending against it.170- "Beads say we already did X" → STOP. Verify against current state (`git log`, PR list, ticket states) before recommending from stale memory.171172## Common mistakes173174- **Assuming a status name exists**: always run `list_issue_statuses` for your team rather than assuming names like "Awaiting Customer" exist.175- **Conflating Linear and external lifecycles**: only `completed`-type status closes linked external issues. `Blocked` keeps them open.176- **Sweeping without a notebook**: a bead-per-ticket is the discipline that lets you walk away mid-sweep and resume cleanly.177- **Recommending from stale bead memory**: beads are notes frozen in time. Verify file paths, PR existence, and ticket states against current reality before acting on them.