Give open issues an explicit disposition (fix, close, or defer with a reason), verifying each claim and grilling where needed, and write agent briefs for the fixes. Works on one issue, one repo, or every philoserf repo.
Installs into .claude/skills of the current project.
Sponsors
SSkills DirectorySkills Directory
Is that skill safe to install?
SSkills DirectorySkills Directory
Know which skills are safe — weekly.
Are you the author of Triage?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/philoserf-triage)
---
name: triage
description: Give open issues an explicit disposition (fix, close, or defer with a reason), verifying each claim and grilling where needed, and write agent briefs for the fixes. Works on one issue, one repo, or every philoserf repo.
disable-model-invocation: true
---
# Triage
Every open issue in a triage pass leaves it with exactly one **disposition**:
- **Fix**: worth doing, specified well enough to start. Post an agent brief.
- **Close**: not worth doing, already done, or a duplicate.
- **Defer**: worth keeping, not now. Post the reason and what would change it.
Issue-tracker operations and labels are in `~/.claude/references/github-tracker.md`. Read it
first. Readiness is not a label: an open issue with no open blockers and no assignee is ready
to take, and `/implement` picks it up from there. Triage keeps that true by blocking or
assigning everything that is not ready.
## Scope
The user names the scope when invoking `/triage`:
- **One issue** (`#42`, or a URL): triage it.
- **A repo** (run inside a clone, nothing named): every open issue in it.
- **The workspace** (run in `~/source/philoserf`): every open issue in every repo one level
down, skipping `obsidian-vault-changelog`.
A request like "what needs my attention?" means the untriaged issues in scope, oldest first.
An issue is **triaged** when it has a triage comment (see [Comments](#comments)) newer than its
last edit and its last non-triage comment.
## Triage one issue
1. **Gather context.** Read the body, comments, labels, assignees and blockers. Read any earlier
triage comment, and don't re-ask what it settled. Explore the code in the area, using `GLOSSARY.md` vocabulary (at the root or in `docs/`) and respecting ADRs where they exist.
2. **Check for prior art.** Search the code for an existing implementation of the request, by
domain concept rather than the issue's wording, and say where you looked. Search closed
issues (`gh issue list --state closed --search "<concept>"`) for a duplicate or an earlier
`wontfix`, and surface any hit.
3. **Verify the claim.** For a bug, reproduce it. For an audit issue (a `**Severity:**` line and
a `## Suggested fix`), verify the Description and Location against current code: line
numbers drift. The report is the specification; the suggested fix is one option among
several, so design the fix yourself. Report what happened: confirmed (with the code path),
refuted, or not enough detail.
4. **Recommend.** Give the disposition, the category label, and the severity where it applies,
with your reasons. Wait for the user's direction.
5. **Grill if needed.** If a fix isn't specified well enough to brief, call the Skill tool twice,
for "grilling" and "domain-modeling", and work it into shape.
6. **Apply** (see below).
## Triage a pass
For a repo or the workspace, do steps 1–4 for every open issue, delegating per-repo
exploration to subagents when the pass is large. Then present one table: repo, issue, title,
disposition, category, severity, and a one-line reason. The user confirms or overrides rows
in one go; then apply them all.
An issue that `/to-spec` or `/to-tickets` produced is already specified: its disposition is
**fix**, and it needs no brief. Check only that its blockers are still right.
End the report with an explicit **Parked** list: every issue deferred, with its reason and
what would unblock it.
## Apply the disposition
Writes go to public issues, so make them only after the user has confirmed the disposition.
Labels follow the tracker reference: exactly one category label, a `severity:` label
mirroring any `**Severity:**` line, and only labels the repo already has.
- **Fix**: post an agent brief ([AGENT-BRIEF.md](AGENT-BRIEF.md)). If the work needs a human
(judgment calls, credentials, external access, manual testing), assign the user and say
why in the brief; otherwise leave it unassigned.
- **Close**:
- **Already implemented**: say where it lives, then
`gh issue close <n> --reason completed`.
- **Duplicate**: name the issue it duplicates, label `duplicate`, then
`gh issue close <n> --reason "not planned"`.
- **Rejected**: give the durable reason (scope, design, a trade-off), not "not now", label
`wontfix`, then `gh issue close <n> --reason "not planned"`. The closed issue is the record
the next prior-art search finds.
- **Defer**: post the reason and the trigger that would bring it back. If the trigger is another
issue, add a native blocking edge on it. Otherwise (a date, an upstream release, an answer
from the reporter) assign the user, so the issue drops off the ready list.
## Comments
Every comment triage posts starts with this marker, which is also how the next pass knows an
issue was triaged:
```markdown
> _This was generated by AI during triage._
## Triage: <fix | close | defer>
```
When the reporter isn't the user and the issue needs more from them, defer it with this body:
```markdown
**What we've established so far:**
- point 1
**What we still need from you (@<reporter-login>):**
- question 1
```
Questions must be specific and answerable. Once the reporter replies, the issue counts as
untriaged again.