بنقرة واحدة
issue-triage
Decision-ready triage — classify, dedupe, and emit a verdict + next action per new GitHub issue
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Decision-ready triage — classify, dedupe, and emit a verdict + next action per new GitHub issue
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Audit every enabled skill's upstream file dependencies for staleness — flags chained skills about to consume yesterday's article or a long-dead topic file
Audit .github/workflows and composite actions with zizmor + actionlint, classify findings against the prior audit, auto-fix Critical/High regressions, and open a PR only when something actually changed.
Weekly API cost report — computes dollar costs from token usage, flags anomalies, forecasts burn, and prescribes concrete optimizations
Weekly partial-correlation of compute economics against a Hyperliquid macro basket — DePIN-token proxy track runs every week (n>180d), sweep-P&L track defers until n≥30 joined days
Score frontier LLMs (Claude, GPT, Gemini, DeepSeek, Grok) on a private compute-markets task corpus, track score deltas across releases, flag public-vs-private divergence
Save a note as one or more atomic notes under memory/notes/ (and optionally Supernotes). Splits bundled inputs into separate atomic files.
| name | Issue Triage |
| description | Decision-ready triage — classify, dedupe, and emit a verdict + next action per new GitHub issue |
| var | |
| tags | ["dev"] |
${var} — Repo (
owner/repo) to triage. If empty, triages all watched repos.
If ${var} is set and does not match owner/repo, abort with issue-triage: invalid var — expected owner/repo and exit. If ${var} is set, target only that repo.
A maintainer's scarce resource is decision time, not labels. For every new issue this skill emits one of four verdicts so the maintainer can act in under 30 seconds:
| Verdict | Meaning | Action taken |
|---|---|---|
| ACCEPT | Clear, in-scope, actionable | Apply type + priority labels (+ area if inferable); suggest reviewer if CODEOWNERS resolves |
| NEEDS-INFO | Missing repro, version, env, or scope | Apply needs-info; post ≤3 specific questions |
| DUPLICATE | Overlaps an open or recently-closed issue | Apply duplicate; reference the original; close only if high-confidence |
| DECLINE | Off-topic, out-of-scope, or spam | Apply wontfix or invalid; suggest alternative venue if any |
Reads repos from memory/watched-repos.md:
# memory/watched-repos.md
- owner/repo
- another-owner/another-repo
If the file is missing and ${var} is empty, log ISSUE_TRIAGE_OK no-watched-repos and exit.
Read memory/MEMORY.md for context.
Read memory/triaged-issues.json (if present; else treat as {}) for previously-triaged issue numbers per repo.
Read the last 7 days of memory/logs/ as a fallback dedup signal.
If ${var} is set → targets = [${var}]. Else targets = non-comment, non-blank lines from memory/watched-repos.md with - prefix stripped.
Per-run budget: ≤10 new issues per repo (tunable — raise/lower as repo volume demands). If more, triage the N oldest and log the overflow.
For each target repo, first detect write access (determines whether this run can apply labels/comments/close, or must run advisory-only):
# One probe per repo. push OR triage permission is enough to label/comment/close.
# Capture stdout AND exit status separately so a genuine "no access" (a clean
# `false` from GitHub) is distinguished from a transient command failure
# (rate limit, network hiccup, outage), which must NOT be read as no-access.
probe=$(gh api "repos/owner/repo" --jq '.permissions.push or .permissions.triage' 2>/dev/null)
status=$?
Branch on status and probe — there are three distinct outcomes, and only an explicit false may trigger advisory mode:
status != 0 (probe errored) — the call failed transiently; permission is unknown, not denied. Skip this repo for the entire run: do not classify, do not apply any write, and do not record anything to memory/triaged-issues.json for it. Recording on an errored run would permanently skip those issues on future runs (§6/§8) even though no labels/comments were ever applied. Log ISSUE_TRIAGE_WARN probe-failed owner/repo and move to the next target.status == 0 and probe == "false" — GitHub answered and the token lacks write/triage permission → set advisory[owner/repo] = true. In advisory mode the run still classifies and emits verdicts, but must not attempt any gh label create, gh issue edit, gh issue comment, or gh issue close call — those fail with HTTP 404 / does not have the correct permissions and are pure noise. Instead it records verdicts to a memory report and surfaces them via notify (see §5–6, §9).status == 0 and probe == "true" — run normally (apply labels + comments + close per the rules below).# Cache existing label set once per repo so we know which labels to auto-create
gh label list -R owner/repo --json name,color --limit 200 > .cache/labels-${owner}-${repo}.json
# Open issues opened in the last 48h (gh issue list excludes PRs by default)
gh issue list -R owner/repo --state open \
--json number,title,body,labels,author,createdAt,comments,reactionGroups \
--search "created:>=$(date -u -d '48 hours ago' +%Y-%m-%d)" \
--limit 25
Filter out issues whose number is already present in memory/triaged-issues.json["owner/repo"] or already carries any of type:*, priority:*, needs-info, duplicate, wontfix, invalid, urgent, bug, feature, question, docs, chore, security, good-first-issue. (Pre-existing labels = already triaged.)
If zero candidates across all repos, log ISSUE_TRIAGE_OK no-new-issues and exit.
For each candidate, query recent issues (open + closed) on the same repo:
gh search issues "is:issue" --repo owner/repo --limit 50 \
--json number,title,state,url,createdAt
Mark as likely duplicate if any of:
#123, "same as", "related to")If duplicate: verdict = DUPLICATE, skip classification, record the referenced issue number.
From title + body + first 3 comments, emit a classification record:
bug, feature, question, docs, chore, securityp0 (security / data loss / outage / blocker), p1 (high-impact bug or high-demand feature), p2 (normal), p3 (nice-to-have)area is identifiedVerdict:
type=security OR priority=p0 → verdict ACCEPT with urgent label addedneeds-info=true → verdict NEEDS-INFOAdvisory mode (advisory[owner/repo] == true): skip this entire step. Do not create or add labels — collect the would-be label set into the issue's advisory record (§6) instead.
Collect the full label set for the issue. For each label:
| Label | Color | Description |
|---|---|---|
bug, feature, question, docs, chore, security | #1d76db | type: |
priority:p0 | #b60205 | priority: critical |
priority:p1 | #d93f0b | priority: high |
priority:p2 | #fbca04 | priority: normal |
priority:p3 | #c5def5 | priority: low |
needs-info | #fbca04 | awaiting reporter response |
urgent | #b60205 | security or p0 |
duplicate | #cfd3d7 | duplicate of another issue |
good-first-issue | #7057ff | well-scoped for newcomers |
wontfix, invalid | #e4e669 | declined |
# Wrap label creation in try/log — if the API returns 422 (already-exists race, protected label, etc.),
# log ISSUE_TRIAGE_LABEL_SKIPPED: <name> and continue rather than aborting the whole run.
gh label create "<name>" -R owner/repo --color <hex> --description "<text>" \
|| echo "ISSUE_TRIAGE_LABEL_SKIPPED: <name>" # only if missing
gh issue edit <N> -R owner/repo --add-label "<comma-separated-set>" \
|| echo "ISSUE_TRIAGE_LABEL_SKIPPED: issue=<N>" # one call per issue
Batch all labels for an issue into one --add-label call to save API quota. A failure on a single label skips only that label (or that issue's labeling) — the rest of the triage (comment, state update) proceeds.
Advisory mode (advisory[owner/repo] == true): do not post any comment or close any issue. Instead append the verdict to an advisory report at memory/triage-advisory/${owner}-${repo}.md (create the dir if missing) so the maintainer can act manually:
## <YYYY-MM-DD> advisory triage (no write access — verdicts only)
- #<N> — <VERDICT> — <type>/<priority>[, area=<area>] — would-label: <label set> — <one-sentence rationale> — <issue url>
Still record the issue in memory/triaged-issues.json (§8) so it is not re-triaged, and surface the advisory batch via notify (§9). Skip the rest of this step.
One comment, one verdict — no boilerplate. Use the template that matches the verdict:
ACCEPT:
**Triage:** ACCEPT — <type>/<priority>[, area=<area>]
<one-sentence rationale>.
Suggested reviewer: <@handle from CODEOWNERS or most-recent committer to the touched files> ← omit this line if not inferable
NEEDS-INFO:
**Triage:** NEEDS-INFO
<one-sentence rationale>.
To proceed we need: 1) <specific question>, 2) <specific question>[, 3) <specific question>]
DUPLICATE:
**Triage:** DUPLICATE of #<N> — <linked title>
<one-sentence reason the match is high-confidence>.
DECLINE:
**Triage:** DECLINE
<one-sentence reason>. <Alternative venue or tool if any>.
gh issue comment <N> -R owner/repo --body "<rendered comment>"
Close rule: only close on DUPLICATE and only when the match is high-confidence (title overlap ≥ 85 % AND identifying string match OR explicit reference). Otherwise leave open with duplicate label:
gh issue close <N> -R owner/repo --reason "not planned" --comment "Closing — duplicate of #<N>."
Never close on ACCEPT, NEEDS-INFO, or DECLINE.
When the issue body or stack trace names a file path path/to/file.ext, try:
gh api "/repos/owner/repo/contents/.github/CODEOWNERS" --jq '.content' 2>/dev/null | base64 -d
gh log -R owner/repo -- path/to/file.ext 2>/dev/null | head -1 # most recent author if CODEOWNERS absent
If neither resolves, omit the line. Do not guess.
Write memory/triaged-issues.json:
{"owner/repo": [{"n": 42, "at": "2026-04-20"}, ...]}
Record only repos that were actually processed this run — those that ran normally or in advisory mode. Never record a repo whose §2 probe errored (it was skipped without classification); recording it would permanently suppress its issues on future runs even though nothing was triaged. Drop entries older than 90 days to keep the file bounded.
Fire ./notify only if the run produced any: urgent / p0 / security / DUPLICATE-close, or any advisory-mode verdicts (since no labels/comments were written, notify + the advisory report are the only output surface). Skip notify for routine p2/p3 triage on write-access repos.
For advisory repos, include a one-line pointer:
- owner/repo — N advisory verdicts (no write access) → memory/triage-advisory/owner-repo.md
*Issue Triage — ${today}*
Triaged N across M repos. Urgent: k. Duplicates closed: d. Needs-info: i.
- owner/repo#123 — urgent (security): <title>
- owner/repo#124 — duplicate of #99 (closed)
If nothing actionable, no notification.
Append to memory/logs/${today}.md:
### issue-triage
- Repos: <list>
- Triaged: N (accept=a, needs-info=ni, duplicate=d, decline=de)
- Urgent / p0: <comma-separated URLs, or "none">
- Skipped (already triaged): <count>
- Overflow (budget > 10): <repos with count, or "none">
- Advisory (no write access): <per-repo count, or "none">
- Source status: <per-repo: ok | fail — reason>
Terminal log lines:
ISSUE_TRIAGE_OKISSUE_TRIAGE_ERROR source-status=<...> (no notification)Use gh CLI for all GitHub operations — it handles auth internally and bypasses curl sandboxing. If gh errors on a single repo, record fail — <reason> in source status and skip that repo; do not abort the whole run. If gh is unavailable entirely, WebFetch cannot substitute (auth required) — log ISSUE_TRIAGE_ERROR gh-unavailable and exit.
gh issue list excludes them; if a query is switched to gh search issues, keep is:issue in the filter.good-first-issue on security or p0 items.memory/triaged-issues.json or already carrying a triage label (§2).false — run advisory-only and record verdicts to memory/triage-advisory/.