/issue-triage — investigate a GitHub issue
SkillFiles & storageInvestigate a JellyRock GitHub issue end-to-end. Fetches the issue body and comments via gh, parses YAML-form fields, classifies (bug / feature / enhancement / arch-decision-needed), identifies the probable code area, assembles initial file context, writes a handoff packet to `.claude/handoffs/`, and continues into the investigation contract at sibling [`INVESTIGATION.md`](INVESTIGATION.md) — validate, root-cause, semi-auto fix or 2-3 tradeoff'd options. Dedup-first: a recent unchanged triage on the same issue short-circuits to the existing handoff. Use when you have an issue number and want to act on it.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the /issue-triage — investigate a GitHub issue skill
What this skill tells your AI
The instructions your AI receives, as published by jellyrock/jellyrock in .claude/skills/issue-triage/SKILL.md and read by ahel’s review.
Single-file workflow: prep + investigation, end-to-end on opus, in main thread, no Task delegation. The mechanical prep (Steps 1-7) produces a handoff packet that's written to .claude/handoffs/ for cross-session resume + compaction recovery + /catchup discovery. The investigation contract — validate, root-cause, semi-auto-fix or present-options — is in sibling INVESTIGATION.md and is followed in main thread once Step 7 completes.
Contract
Goal. Take a GitHub issue number and drive it from "filed" to "acted on" end-to-end, in one main-thread session. The mechanical prep — fetch the issue and comments, parse the YAML-form fields, classify (bug / feature / enhancement / arch-decision-needed), identify the probable code area, and assemble initial file context — feeds the investigation contract in sibling INVESTIGATION.md (validate, root-cause, then a semi-automatic fix or 2-3 tradeoff'd options). It runs on Opus because classification, area-mapping, and root-cause investigation are real judgment over real code, not template fill — a wrong area or a misclassification sends the whole investigation off course. It is dedup-first: a recent unchanged triage on the same issue (cited files untouched, working tree clean, no new issue activity) short-circuits to the existing handoff. Reach for it when you have an issue number you want to act on.
Inputs. $ARGUMENTS is the required issue number (e.g., 419); if empty, prompt for it. The skill reads the issue and its comments via gh issue view, the codebase via git ls-files / git log / Grep, the architecture topic docs (docs/architecture/*.md related-files frontmatter), and any prior handoff at .claude/handoffs/issue-<N>-*.md for the dedup check.
Outputs. A handoff packet written to .claude/handoffs/issue-<N>-<timestamp>.md with YAML frontmatter (created, target, branch, sha, cited-files) and a body carrying the classification, probable area, 2-5 cited initial-context files, and the full untruncated issue body + comments — durable for cross-session resume, compaction recovery, and /catchup discovery; a one-line confirmation of the saved path, classification, area, and file count; and then the in-thread investigation per INVESTIGATION.md. On a clean dedup hit, no new file is written — the prior handoff is surfaced with resume/re-triage/cancel options.
Success criteria.
- The dedup check runs first and short-circuits correctly: all three signals clean (cited files untouched, working tree clean for them, no new issue activity) → surface the prior handoff and STOP for the user's pick; any signal changed → proceed.
- The issue is classified correctly from labels + body shape (body shape wins on label conflict), with genuinely ambiguous cases surfaced to the user.
- The probable area is identified from the keyword→area map; multiple matches are listed for the investigator rather than forced to one; no match is surfaced honestly as "uncertain area."
- Initial file context is 2-5 genuinely relevant files (quality over quantity, not padded).
- The handoff is written with valid frontmatter and untruncated bodies, then the skill continues immediately into
INVESTIGATION.mdas one motion.
Failure modes to avoid.
- Re-prepping over a clean dedup hit. If all three signals are clean, do not write a new file — surface the prior handoff and wait for the user's pick.
- Forcing a classification or area when ambiguous. Surface conflicting labels (trust body shape), list multiple matching areas, and flag "uncertain area" rather than guessing — a wrong call misdirects the whole investigation.
- Padding the initial file context. Pick the 2-5 files that actually matter; the investigator reads more as it goes.
- Truncating the issue body or comments. Keep them full — diagnosis needs the complete text.
- Running the investigator on a support question. If the body is a how-does-it-work question, redirect to the contact links rather than triaging.
- Stopping after the handoff. Step 7 is "save the handoff AND continue into investigation" as one motion; don't write the file and wait.
When NOT to use.
- The issue is a support question (how a feature works, not a bug/feature/enhancement) — direct the reporter to the contact links in
.github/ISSUE_TEMPLATE/config.yml. - The issue is a duplicate — if a quick search shows it duplicates an existing one, comment to consolidate rather than triage.
- The issue is closed and was resolved — there's nothing to investigate; ask the user to clarify if they want to revisit.
- The issue body is empty (filed via the old templates) — comment requesting more info before triage.
Implementation
Inputs
$ARGUMENTS: required issue number (e.g., 419). If empty, prompt for it.
Step 0 — Check for prior triage (dedup)
Before any prep, look for a recent handoff on this issue:
ls -t .claude/handoffs/issue-<N>-*.md 2>/dev/null | head -1
If a prior handoff exists, Read it. The handoff has a YAML frontmatter with created, branch, sha, cited-files. Check three signals:
- Cited files unchanged?
git log <sha>..HEAD -- <cited-file-1> <cited-file-2> ...— empty output means no commits touched them on this branch. - Working tree clean for cited files?
git status --porcelain -- <cited-files>— empty means no uncommitted changes. - Issue itself unchanged?
gh issue view <N> --json updatedAt— compare to the frontmatter'screated. If the issue'supdatedAtis older thancreated, no new activity.
If all three are clean, do not write a new file. Surface to the user:
Prior triage exists at
.claude/handoffs/issue-<N>-<timestamp>.mdfrom . Cited files unchanged (sha ..HEAD has no commits on them, working tree clean), and the issue has no new activity since. Options:
- (a) Resume from the existing triage — Read the handoff and follow
INVESTIGATION.mdfrom there- (b) Re-triage anyway — fresh prep, new handoff file (use this if you suspect the prior prep itself was wrong, or want a different angle)
- (c) Cancel
Then STOP. Wait for the user's pick before proceeding.
If any signal shows change (or no prior handoff exists), proceed to Step 1.
Step 1 — Fetch the issue
gh issue view <N> --json number,title,body,state,labels,author,comments,createdAt,updatedAt,closedAt
If the issue is closed, ask whether to proceed (sometimes you want to revisit a closed issue; usually not). If the issue is a question (the YAML schema doesn't fit either bug/feature/enhancement and the body is a question for support), surface that and suggest the user direct the reporter to the contact links in .github/ISSUE_TEMPLATE/config.yml — /issue-triage isn't the right tool for support questions.
Step 2 — Parse the YAML-form fields
Issues filed via the upgraded YAML templates have predictable structure: each form field renders as ### <Field label> followed by the user's value. Parse:
For bug_report.yml issues:
- Description ("What happened?")
- Steps to reproduce
- JellyRock client version
- Roku device info
- Server connection type
- Jellyfin server version (optional)
- Logs (optional)
- Screenshots (optional)
For feature_request.yml / enhancement_request.yml: simpler shape (problem + solution, or existing-feature + proposed-change).
If the issue was filed via the OLD markdown templates (.md), the structure is more freeform. Extract what you can; the investigator will handle gaps. If the body is genuinely raw text with no structure, just pass it through verbatim.
Step 3 — Classify
Map labels + body shape to a classification:
- bug —
buglabel is present OR body shape matches bug_report.yml (has repro steps + version info). Subcategory:arch-decision-neededif the bug crosses architectural seams (multiple components, cross-cutting concerns, or the diagnosis would force a choice between minimal-fix and refactor). - feature —
feature-requestlabel OR body shape matches feature_request.yml (has problem + proposed solution). - enhancement —
enhancementlabel OR body shape matches enhancement_request.yml.
If two labels conflict (bug AND enhancement), trust the body shape over the labels. If neither label fits, surface that and ask the user to disambiguate.
Step 4 — Identify probable area
Map keywords in the title + body + labels to JellyRock areas. Use this map as a starting point:
| Keywords | Probable area |
|---|---|
| video, playback, player, OSD, trickplay, transcode, DoVi, AV1, multichannel, surround | components/video |
| library, ContentNode, SceneManager, data, items grid | components/data |
| api, jellyfin, request, task, http, auth, login | source/api |
| translation, locale, language, i18n, en_US | locale |
| util, helper, registry, config, global state | source/utils |
| component, scene, focus, navigation, dialog, menu, button | components |
| migration, bootstrap, main entry | source |
| test, rooibos, spec | tests |
| build, lint, BSC plugin, generator script | scripts |
If multiple areas match, list them and let the investigator decide. If no area matches, surface that as "uncertain area" and let the investigator search.
Step 5 — Assemble initial file context
For the probable area, surface up to 5 files the investigator should read first:
# Files in the probable area
git ls-files <area>/ | head -20
# Recent commits in the area (often the right starting point — what changed
# recently might have introduced the bug)
git log --oneline -10 -- <area>/
# Architecture topic doc for the area (find via related-files frontmatter)
grep -lE "^ - <area>" docs/architecture/*.md
Pick 2-5 files that look most relevant based on the issue body. Don't pad — quality over quantity. The investigator will read more as it goes.
Step 6 — Build the handoff packet
Construct the packet with a YAML frontmatter (so future Step-0 dedup checks can read it) plus the prep body:
---
created: <ISO-8601 UTC timestamp from `date -u +%Y-%m-%dT%H:%M:%SZ`>
target: issue-<N>
branch: <git rev-parse --abbrev-ref HEAD>
sha: <git rev-parse --short HEAD>
cited-files:
- <path-1>
- <path-2>
---
Issue #<N>: <title>
Status: <open | closed>
Labels: <comma list>
Reporter: @<login>
Filed: <date>
Classification: bug | feature | enhancement | arch-decision-needed
Probable area: <area>
Initial file context:
- <path>:<line range or whole-file> — <one-line why-relevant>
- ...
Issue body:
<full body, untruncated>
Comments:
<@author>: <body>
<@author>: <body>
Keep bodies untruncated — full text is needed to diagnose.
Step 7 — Write the handoff and continue into investigation
-
Compute the timestamp once:
date +%Y%m%d-%H%M%S(for the filename) anddate -u +%Y-%m-%dT%H:%M:%SZ(for the frontmatter). -
Write the packet to
.claude/handoffs/issue-<N>-<YYYYMMDD-HHMMSS>.md(gitignored; durable for compaction recovery + cross-session resume +/catchupdiscovery). -
Output a single confirmation line, this exact shape:
Handoff saved:
.claude/handoffs/issue-<N>-<timestamp>.md(classification: , probable area: , files cited). Now followingINVESTIGATION.md— adjust scope freely. -
Then continue immediately into the investigation contract at sibling
INVESTIGATION.md. Don't stop or wait — Step 7's "save the handoff + continue" is one motion.
Sub-agent invocation
To invoke from a parent sub-agent (rare): parent passes Read .claude/skills/issue-triage/SKILL.md and follow Steps 0-7 for $ARGUMENTS=<issue-number>; write the handoff file but stop before INVESTIGATION.md — surface the handoff path so the parent can decide next in the Task prompt. Sub-agents only run the prep; they don't follow INVESTIGATION.md (which is interactive). If you discover any decisions or followups during this work, surface them at the end of your report as a Captures for /log section. I'll invoke /log for each. Do not write to docs/ directly.
Signals
- GitHub stars
- 41
- Forks
- 2
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
issue-triage-jellyrock- Source
- github.com/jellyrock/jellyrock