mcpbeat

Triage Issues

microsoft/triage-issues

>-

8k tokens
context cost
the whole folder, loaded on every use
4
files
instructions only
0
copies elsewhere
how many repositories repackaged it
20188
stars on the repo
on the repository, not the skill itself

Install

one command, takes just this skill from the repository
npx skills add https://github.com/microsoft/fluentui --skill triage-issues

What comes with it

13 828 bytes besides the instruction
references/partner-orgs.md
references/shield-guidelines.md
references/triage-labels.md

What it tells the agent to use

found in the instruction text
Bash runs shell commands — read the instruction before connecting

The instruction itself

16 sections, as written by the author

Triage Fluent UI Issues (Shield Workflow)

Your job is to walk the current Needs: Triage :mag: queue on microsoft/fluentui, classify each issue against the Shield triage rules, and apply the right labels / assignee after the user approves.

This skill operates in recommend-then-apply mode: never mutate issues until the user has approved the batch. A wrong label is cheap to add and annoying to remove, so lean on the approval step.

The triage queue

gh issue list --repo microsoft/fluentui \
  --search 'is:open is:issue label:"Needs: Triage :mag:"' \
  --limit 50 \
  --json number,title,author,labels,createdAt,body,comments

Sort oldest-first — the guidelines prioritize the longest-waiting issues.

The decision each issue needs

For every issue, you're producing a recommendation with these fields:

| Field | Possible values |

| ---------------------- | ------------------------------------------------------------------------------------ |

| classification | bug, feature, question, a11y, needs-repro, duplicate, not-an-issue |

| product | v9, v8, web-components, charting, unknown |

| is_partner_ask | true / false (see references/partner-orgs.md) |

| priority_signal | p1, normal, help-wanted, good-first-issue |

| add_labels | list of label names to add |

| remove_labels | list of label names to remove (always includes Needs: Triage :mag: once triaged) |

| assignee | GitHub login of the area owner (see routing table below) |

| comment | optional message to leave for the author (required if asking for more info) |

| validation_candidate | true / false — does this bug warrant a playwright-cli repro check before triage? |

| needs_human_followup | anything you're unsure about — surface it, don't paper over it |

Don't invent labels. Every label you recommend must exist in the repo — see references/triage-labels.md for the allow-list.

Classification rules (from Shield guidelines)

Read references/shield-guidelines.md for the full rules. The short version:

  • Questions → convert to a GitHub Discussion; don't triage as an issue.
  • Bug with clear repro:
  • Assign area owner (see routing below).
  • If the report documents a critical regression (measured impact, root-cause analysis, broad blast radius) → recommend Shield: P1 and flag needs_human_followup so the user can post in the Shield Teams channel. This decision is about the report, not the reporter.
  • If you have private notes (via memory) indicating the author is on a tracked partner workstream AND the body references that workstream → recommend Partner Ask as well. When in doubt, leave the label off and flag for human verification — see references/partner-orgs.md.
  • If product version is v9 or v8 → normal flow. v9 bugs always get resolution preference.
  • If version is v7 → recommend Resolution: Won't Fix with a polite comment, unless the report has exceptional business impact signals that warrant an exception.
  • Bug without a reliable repro → recommend Needs: Repro + Needs: Author Feedback, draft a comment asking for a minimal reproduction (StackBlitz preferred).
  • Feature request:
  • First, check whether it's a "port v8 behavior to v9" ask. If the body cites a v8 component/prop that v9 doesn't have, investigate before backlogging. v9 deliberately rebuilt many APIs around composition (Field wraps controls, motion lives in react-motion-components-preview, announcements via useAnnounce, etc.). There's usually a v9-native pattern already documented — see the investigation step below.
  • If a v9-native pattern exists → recommend Resolution: By Design + close, with a comment pointing the reporter to the pattern. This keeps the backlog honest.
  • If there's no v9 equivalent and the ask is valid for v9 → Needs: Backlog review.
  • For older versions → likely close as out-of-support unless partner ask.
  • Accessibility-related (mention of screen readers, WCAG, keyboard nav, aria-\*, focus order, contrast, etc.) → add Area: Accessibility and assign smhigley alongside the area owner.
  • DuplicateResolution: Duplicate + comment linking the original. Before claiming a duplicate, actually search: gh issue list --repo microsoft/fluentui --search '<keywords>' --limit 10.
  • Spam / not-an-issueResolution: Not An Issue, close.

Area-owner routing

Route to people first, then to teams. Teams are in docs/team-routing.md and .github/CODEOWNERS is the source of truth for package ownership.

| Area | Assignee | Trigger |

| ---------------------------------------------------------------- | ----------------------------------------- | ------------------------------------------------------------------------ |

| Web Components (@fluentui/web-components, Fluent UI WC (v3)) | chrisdholt | Any web-components label, or title mentions fluent-* custom elements |

| Charting (@fluentui/charts) | AtishayMsft | Package: charting, chart component names |

| Date/Time pickers | ermercer | DatePicker, Calendar, TimePicker |

| Accessibility (any product) | smhigley | a11y keywords; also assigned in addition to product owner |

| v9 React components | CODEOWNERS owner for the specific package | Everything under packages/react-components/* |

| v8 React components | CODEOWNERS owner for the specific package | Everything under packages/react/* |

For v9/v8 components, look up the package owner. Fast path:

# Example: find the CODEOWNERS entry for react-skeleton
grep -n 'react-skeleton' .github/CODEOWNERS || true

If CODEOWNERS lists a team (e.g., @microsoft/cxe-prg), leave assignee empty and put the team in needs_human_followup — teams can't be assigned on issues via gh, so the user will route manually.

Priority and partner-ask signals

Every issue goes through the same decision tree regardless of author — that's the default. Shield: P1 and Partner Ask are narrow exceptions, not shortcuts around triage.

See references/partner-orgs.md for the framing (what these labels mean, what they _don't_ mean, and how to avoid misusing them).

If the triager has private notes in their Claude memory about tracked partner workstreams and known reporter handles, use that context to tip ambiguous cases. If no such memory exists, treat affiliation as unknown and flag needs_human_followup: "verify partner status" rather than guessing. A wrong Partner Ask label is a worse outcome than a missing one — the label can be added in five seconds later.

Workflow

Step 1 — Fetch

Run the queue query. Show the user the count and a one-line summary per issue (number, title, author, age in days). Don't dump the full JSON.

Step 2 — Classify

For each issue, read the title + body + existing labels. If repro evidence is ambiguous, skim the linked StackBlitz / attached code block — don't mark it needs-repro just because the word "Reproduction" field in the template is empty; check the actual content.

For feature requests that cite v8 behavior, do a targeted investigation before deciding. Look in the relevant package for:

  • packages/react-components/react-<name>/library/docs/Spec.md — design rationale
  • packages/react-components/react-<name>/library/docs/MIGRATION.md — explicit v8→v9 migration notes, often documents dropped props and their replacements
  • packages/react-components/react-motion-components-preview/ — motion/transition primitives (if the ask is animation/transition related)
  • packages/react-components/react-field/ — label/description/validation composition (if the ask is form-control adornments)
  • The component's stories for worked examples of the composition pattern

v9 defaults to composition over configuration. An ask like "add a shouldFadeIn prop" usually has an answer like "compose with <Fade>" or "use onLoad + makeStyles keyframes". Surface the v9 pattern in the comment so the reporter isn't left hanging.

When checking for duplicates, search first:

gh issue list --repo microsoft/fluentui \
  --search 'is:issue <keywords>' \
  --limit 10 \
  --json number,title,state

Keep each issue's classification in an in-memory structure (don't write intermediate files).

Step 3 — Present recommendations

Produce a compact table the user can scan. One row per issue. Columns: #, classification, add labels, remove labels, assignee, priority, notes. Put the comment drafts separately below the table, keyed by issue number — comments are long and clutter the table.

If you found duplicates or partner asks, call them out explicitly above the table.

Then propose a validation set. Below the table, list the bugs you flagged as validation_candidate: true with a one-line reason each, and ask the user to confirm. Take the initiative here — don't wait for the user to think of validation. Example:

I'd like to verify these repros with playwright-cli before triaging:
  • #35998 — StackBlitz provided; Link underline visual bug, testable headless
  • #36001 — CodeSandbox provided; Button click handler not firing

Confirm with `validate yes`, `validate all`, a subset like `validate 35998`,
or `skip validation` to move straight to approval.

If there are no validation candidates (all feature requests, all reports with root-cause diffs, etc.), say so explicitly and go straight to Step 4.

How to decide validation_candidate:

true when all of:

  • The issue is a bug (not a feature or question).
  • A reproduction exists — either a sandbox URL (StackBlitz / CodeSandbox / JSFiddle / CodePen) in the body, or a clearly-described behavior against a specific component that a Storybook default story can exercise.
  • The expected failure is something headless Chromium can observe: visual layout, DOM structure, console errors, aria attributes, event handlers firing.

false when any of:

  • It's a feature request (nothing to reproduce).
  • The author already included a root-cause analysis + a suggested diff (they did the work; headless adds noise, not signal).
  • The bug is about performance, memory, or timing (perf A/B metrics, rAF regressions, FCP deltas) — headless won't give reliable numbers.
  • The bug is browser-specific (Edge-only, Safari-only, mobile) — you can't run those from here.
  • The bug requires assistive tech (screen reader behavior, voice control) — headless can see ARIA but not AT interpretation.
  • The bug requires real user timing (typing debounce, drag gestures, animation pauses).

Step 3.5 — Validate repros with playwright-cli

Run this step when the user confirms the validation set you proposed in Step 3 (or when they name a different set — validate 35998 35976, validate all, etc.). If the user says skip validation, go straight to Step 4.

Validation is the human-in-the-loop gate on agent initiative: you proposed the set, the human confirmed it, now execute. Do not mutate any issue as a result of validation — evidence feeds back into the recommendation table, and the user still approves in Step 4.

For each confirmed issue:

  • Prerequisites. Run playwright-cli via npx (same as visual-test, so nothing is installed globally on the user's box). First invocation downloads @playwright/[email protected] into the npx cache; subsequent calls are cached:
   npx -y @playwright/[email protected] <command>
  • Pick the target URL. In priority order:
  • A StackBlitz / CodeSandbox / JSFiddle / CodePen link in the issue body — use it directly.
  • A link to a specific Storybook story hosted at storybooks.fluentui.dev or similar — use it directly.
  • Otherwise: spin up the relevant component's per-component Storybook (e.g. yarn nx run react-<component>-stories:storybook --skip-nx-cache). Follow the full pattern in the visual-test skill for port detection and troubleshooting.
  • Capture evidence. Don't try to "prove" the bug — just gather what a human needs to decide:
   npx -y @playwright/[email protected] goto "<repro URL>"
   npx -y @playwright/[email protected] screenshot --filename=/tmp/triage-<num>-screenshot.png
   npx -y @playwright/[email protected] snapshot > /tmp/triage-<num>-dom.txt
   # Console errors and warnings — often the most useful signal
   npx -y @playwright/[email protected] console > /tmp/triage-<num>-console.txt

If the sandbox has a specific interaction to trigger the bug (click a button, type in a field), follow it using refs from the snapshot.

  • Classify the result as one of:
  • repros — you observed the described behavior. Include the screenshot path and any console errors.
  • does_not_repro — you visited the sandbox, ran through the described steps, and the behavior didn't appear. Include what you tried so the human can sanity-check.
  • cannot_determine — the sandbox didn't load, requires auth, times out, needs a specific browser version (common for perf / Edge-only issues), or needs real user timing that headless can't reproduce. This is the most important category — don't pretend headless gives you environment coverage it doesn't.
  • Feed evidence back into the recommendation. Only update add_labels as follows:
  • does_not_repro → surface Resolution: Can't Repro as a candidate, not a decision. The user still approves. Attach the evidence in the comment draft so they can judge.
  • repros → leave labels unchanged; the existing classification stands. Maybe upgrade priority if the evidence makes it clearly worse than the body described.
  • cannot_determine → leave labels unchanged; note the limitation in needs_human_followup.
  • Clean up. Close the browser, kill any Storybook you started, and delete the evidence files unless the user wants to keep them:
   npx -y @playwright/[email protected] close
   # If you started Storybook:
   lsof -i :$SB_PORT -t 2>/dev/null | xargs kill 2>/dev/null

The validation-candidate heuristics are in Step 3 — don't re-litigate them here. If the user overrides and asks you to validate something you flagged as not-a-candidate (e.g., the Edge perf issue), do it anyway but prefix the result with a warning about headless limitations so the evidence is interpreted correctly.

Step 4 — Ask for approval

Ask the user: "Apply all / approve specific numbers / skip / edit?". Accept inputs like apply 35976, 35977, skip 36007, or free-form edits. The user can still request additional validation at this point (validate 36007 even if you hadn't proposed it); if they do, loop back through Step 3.5 and then re-present the updated table. Don't proceed to apply until the user has explicitly approved.

Step 5 — Apply approved changes

Use gh issue edit for labels and assignees. Use gh issue comment for drafted comments. Apply one issue at a time and print a one-line result per issue (success or error). Do not retry blindly on failure; stop and ask the user what to do.

# Labels
gh issue edit <num> --repo microsoft/fluentui \
  --add-label "Type: Bug :bug:" \
  --add-label "Fluent UI react-components (v9)" \
  --remove-label "Needs: Triage :mag:"

# Assignee
gh issue edit <num> --repo microsoft/fluentui --add-assignee chrisdholt

# Comment (use heredoc)
gh issue comment <num> --repo microsoft/fluentui --body "$(cat <<'EOF'
Thanks for the report! Could you share a minimal StackBlitz or CodeSandbox that reproduces this? The issue template has a Reproduction field that's currently empty.
EOF
)"

Step 6 — Summarize

After applying, print: X issues triaged, Y still need human follow-up (list them), Z were skipped. Leave the user with a clear handoff.

Anti-patterns (don't do these)

  • Don't apply changes silently. Always present the recommendation table first.
  • Don't guess at labels that don't exist. The allow-list in references/triage-labels.md is exhaustive for triage — if a situation calls for a label that isn't there, ask the user.
  • Don't mark issues as duplicates without linking the original. A Resolution: Duplicate label without a comment pointing to the original is worse than no triage.
  • Don't remove Needs: Triage :mag: on issues you're flagging for human follow-up. If you can't decide, leave the triage label on so it stays in the queue.
  • Don't assign a team as if it were a user. gh issue edit --add-assignee only accepts user logins. For team routing, leave the assignee empty and note the team in needs_human_followup.
  • Don't say "we'll fix this soon" in comments. The guidelines are explicit: only promise work we're committed to delivering.

Reference files

  • references/shield-guidelines.md — full triage decision tree from the Shield dev guidelines
  • references/triage-labels.md — exact label names allowed in triage
  • references/partner-orgs.md — what Shield: P1 / Partner Ask mean and, importantly, what they don't

How to use it

Copy the folder

Take microsoft/triage-issues from the repository into ~/.claude/skills for personal use, or into .claude/skills inside a project.

Check the name does not clash

The agent identifies a skill by the name field in its header. Two skills with the same name cannot sit side by side — one of them will be ignored.

Install what it needs

The instructions reference npx. Without those the skill loads but fails at the first command.