skills/sentry-top-issue/SKILL.md
Pick the single highest-priority unresolved Sentry issue and hand it off to a fixer skill. Use when triaging Sentry errors, running automated issue triage, or when asked to fix the top Sentry issue in a project.
npx skillsauth add rolemodel/rolemodel-skills sentry-top-issueInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Skill behaviour
Inputs ($ARGUMENTS)
All optional, space-separated key=value tokens plus bare flags:
Phase 1 — Preflight (scope + gh install + PR cap)
Phase 1a — Run preflight
preflight.sh is the single source of truth for scope discovery, the gh install check, and the open-[SENTRY …] PR cap. Invoke it unconditionally with any explicit values from $ARGUMENTS forwarded as flags — if scope can't be resolved, the script self-skips with a structured reason. Do not pre-check scope yourself; let the script speak.
bash skills/sentry-top-issue/scripts/preflight.sh \
[--org <slug>] [--project <slug>] [--region <url>] [--env <name>] \
[--no-pr-filter] --repo-root "$PWD"
Always echo the script's raw JSON output back to the user verbatim (as a fenced ```json block) so the preflight result is visible in the transcript — regardless of whether the status is ok or skip. This is the preflight's audit trail; do not paraphrase or summarize it away.
Then read the JSON and branch:
{"status":"skip","reason":"..."} — after printing the JSON, print reason verbatim on its own line and exit cleanly. Do not call any Sentry MCP tools, do not invoke AskUserQuestion, do not invoke the fixer, do not proceed to Phase 2. Common skip reasons: missing scope (add organizationSlug/projectSlugOrId to AGENTS.md, or pass org=<slug> project=<slug> as arguments), missing gh when PR filter is on, PR cap reached, or missing jq.{"status":"ok","org":...,"project":...,"region":...,"env":...,"prFilter":<bool>,"openSentryPrs":<n>} — carry these values into Phase 2. openSentryPrs is informational; the cap has already been enforced by the script.Scope precedence (as implemented by the script): explicit flags first, then AGENTS.md / CLAUDE.md / .claude/**/*.md under --repo-root, matching the three-line pattern (organizationSlug, projectSlugOrId, regionUrl) described in references/SCOPE_DISCOVERY.md. Skip reasons the script can emit: missing scope, missing gh (when PR filter is on), missing jq, PR cap reached (default 3, overridable via --pr-cap). gh auth failures are logged to stderr and do not block.
Phase 1b — Verify Sentry MCP is connected
Before calling any Sentry tool, confirm a Sentry MCP server is actually available in this session:
+sentry search_issues) and confirm that search_issues, find_organizations, and find_projects resolve to real tool names under some mcp__*Sentry*__ prefix.Sentry MCP is not connected — skipping.Phase 2 — Fetch candidate shortlist (priority-tiered)
Resolve the Sentry MCP search_issues tool via ToolSearch at runtime (tool name: mcp__<server>__search_issues — prefix varies by MCP server name).
Querying by priority. Embed the literal Sentry filter syntax directly in the natural language query — this is the only reliable method to get the translator to emit issue.priority:<tier>. Phrases like "high priority" or "issue priority level high" cause the translator to drop the filter entirely. Use this exact template:
"unresolved issues with issue.priority:<tier> in environment <env> sorted by frequency"
Iterate priority tiers in order: high, then medium, then low. For each tier, call search_issues with:
organizationSlug, projectSlugOrId, regionUrl from preflightnaturalLanguageQuery per the template above (substitute <tier> and <env>)limit: 10includeExplanation: true on the first call of the run only. Verify the translation includes issue.priority:<tier> (not bare priority:<tier>), is:unresolved, and environment:<env>. If issue.priority: is missing, skip this tier and move to the next — do not retry.The translator may return more than limit results — truncate to the first 10 yourself.
Run Phase 3 filters against each tier's results; stop at the first tier with surviving candidates. If all three tiers are empty after filtering, fall back to one untiered call: "unresolved issues in environment <env> sorted by frequency". If still empty after filtering, print "Nothing to pick." and stop.
Phase 3 — Filter issues already being worked on or already fixed
Unless no-pr-filter is set, drop any candidate that is already handled. Two sub-filters:
Phase 3a — Open PR and recent closed-PR filter
Pipe the candidate IDs through skills/sentry-top-issue/scripts/filter-candidates.sh:
bash skills/sentry-top-issue/scripts/filter-candidates.sh <id1> <id2> ... <id10>
The script prints surviving IDs one per line (empty output = all filtered). Treat its stdout as authoritative. It applies two checks in one pass:
[SENTRY <suffix>] PR (work already in flight).[SENTRY <suffix>] PR within the last 30 days. A recently closed PR indicates the automation already acted on that issue recently; handing the same issue back immediately would risk wasting another PR before the prior attempt has been fully evaluated or deployed.Both checks degrade gracefully when gh is unauthenticated or jq is missing — passing inputs through with a stderr warning — so no extra handling is needed here. (Missing gh is already caught by Phase 1 preflight when the PR filter is on.)
Phase 3b — Merged-commit filter
Catches the case where the fixer skill has already merged a [SENTRY <suffix>] commit but the Sentry issue is still marked unresolved because the release hasn't deployed yet. Without this filter, the skill hands the same issue to the fixer again and wastes a PR.
git symbolic-ref --short refs/remotes/origin/HEAD 2>/dev/null (yields origin/main or origin/master on most repos).origin/main if it resolves via git rev-parse --verify origin/main.origin/master if it resolves via git rev-parse --verify origin/master.main or master as a last resort.-. Examples: ALMANAC-5 → 5, ALMANAC-1G → 1G, PROJECT-123 → 123. This matches the [SENTRY <suffix>] format that the sentry-issue-fixer skill uses for commit subjects (which preserves both numeric and base32-ish Sentry short-ID suffixes).git log <default-branch> --fixed-strings -i --grep "[SENTRY <suffix>]" -n 1 --format=%H. A non-empty result means a merged commit already targets this issue; drop the candidate. This catches squash merges (PR title on the commit), rebase merges (original commits linearized), and regular merges (feature-branch commits are still in the log).Phase 3c — Stale-issue filter
Filter out Sentry issues that have not occurred in the last 7 days to avoid picking stale issues that may have been resolved in a hotfix or are no longer relevant. This is a simple date filter based on the lastSeen field of the issue.
If this filter results in zero candidates, ignore this filter and proceed with the original list of candidates. This ensures that we don't end up with "Nothing to pick." just because all issues are stale, while still preferring more recent issues when available.
Phase 4 — Select and justify
Take the top remaining candidate. Print:
Top issue: <ID> — <title>
Users: <userCount> Events: <count>
First seen: <firstSeen> Last seen: <lastSeen>
Why: ranked #1 by Sentry Trends sort within the highest-priority tier that had surviving candidates (unresolved, environment=<env>, priority=<tier>, no open PR, no merged [SENTRY <suffix>] commit on the default branch).
If the shortlist is empty after filtering, say "Nothing to pick." and stop.
Phase 5 — Handoff
Unless dry-run is set, invoke the fixer skill (default rm-sentry-issue-fixer) via the Skill tool. Pass the selected issue ID plus automatic=true as args — for example: PROJECT-123 automatic=true. The existing fixer's Phase 1 already handles a direct ID input, and a fixer such as rm-sentry-issue-fixer reads the automatic flag to run fully non-interactively and always open a PR. Callers who want a more manual run should invoke the fixer skill directly with automatic=false instead of going through sentry-top-issue.
references/SCOPE_DISCOVERY.md content (summary)
Files to create / modify
┌────────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────────────────────┐ │ File │ Change │ ├────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────┤ │ sentry-top-issue/SKILL.md │ New. The skill as described. │ ├────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────┤ │ sentry-top-issue/LICENSE │ New. MIT. │ ├────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────┤ │ sentry-top-issue/references/SCOPE_DISCOVERY.md │ New. Short reference on how scope is discovered and how to declare it in a project. │ ├────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────┤ │ sentry-issue-fixer/SKILL.md │ No change. New skill composes via Skill tool. │ └────────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────┘
Install location during development: /Users/joshmcleod/.claude/skills/sentry-top-issue/. For publication: the directory is self-contained and can be moved to its own public repo root.
Reused existing pieces
Verification
[SENTRY <suffix>] test filter where <suffix> matches a top candidate's ID suffix (e.g., ALMANAC-5 → 5); rerun in dry-run; confirm that candidate is skipped. Revert the commit.Non-goals
testing
Verify what Ruby versions actually exist and install a specific Ruby via rbenv. Use BEFORE asserting that any Ruby version does or doesn't exist (e.g., "Ruby 4.0 isn't out yet", "the latest Ruby is 3.x", "Ruby X.Y.Z doesn't exist"). Also use when the user asks "what's the latest Ruby", "is Ruby X out", "does Ruby X.Y exist", "install Ruby", "switch to Ruby X", "what Ruby is installed", or mentions a specific Ruby version you're unsure about. Claude's training data may be out of date — run `check.sh` first.
development
Trace code through the stack — upward to entry points, downward to data, or laterally across boundaries. Use when the user asks "where does this get called from", "what calls this method", "trace this through the stack", "how does this request flow", "where does this data come from", "follow this through the code", or pastes/selects a piece of code and wants to understand where it fits in the larger system.
tools
Find and fix issues from Sentry using MCP. Use when asked to fix Sentry errors, debug production issues, investigate exceptions, or resolve bugs reported in Sentry. Methodically analyzes stack traces, breadcrumbs, traces, and context to identify root causes.
development
Perform comprehensive code audits of Ruby on Rails applications based on thoughtbot best practices. Use this skill when the user requests a code audit, code review, quality assessment, or analysis of a Rails application. The skill analyzes the entire codebase focusing on testing practices (RSpec), security vulnerabilities, code design (skinny controllers, domain models, PORO with ActiveModel), Rails conventions, database optimization, and Ruby best practices. Outputs a detailed markdown audit report grouped by category (Testing, Security, Models, Controllers, Code Design, Views) with severity levels (Critical, High, Medium, Low) within each category.