ワンクリックで
pr-triage
First-touch triage for external pull requests - verdict, label, and a welcoming comment within minutes of open
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
First-touch triage for external pull requests - verdict, label, and a welcoming comment within minutes of open
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Run a task through your Executor Cloud tool catalog - one MCP endpoint proxying every integration you connected (MCP servers, OpenAPI specs, GraphQL APIs), with per-tool allow/approve/block policies. OAuth Connect via the dashboard MCP panel.
Live-data research via the glim.sh MCP - web search, full page extraction, X/Twitter, Reddit, GitHub, Amazon, and YouTube transcripts - synthesized into a cited digest. Pay-per-call from the connected account balance; OAuth Connect via the dashboard MCP panel.
Read your Robinhood Agentic brokerage account via the Robinhood Trading MCP - portfolio, buying power, positions, and order history - and place a single operator-instructed trade. OAuth Connect via the dashboard MCP panel.
Business-development radar across your product family - find who's building, forking, integrating, and mentioning your products, ranked into a who-to-talk-to-this-week lead list.
Generate and send a digest on a configurable topic, optionally pulling RSS/Atom feeds as an input source alongside web + X signal
Search and curate X/Twitter behind one selector - keyword, topic roundup, a single or tracked-account digest, an X list, or the AI-agent buzz preset - clustered into signal-scored sub-narratives.
| type | Skill |
| name | PR Triage |
| category | dev |
| description | First-touch triage for external pull requests - verdict, label, and a welcoming comment within minutes of open |
| var | |
| tags | ["dev"] |
${var} — PR scope. Accepts
owner/repo,owner/repo#N, or empty (all watched repos). If empty, scans every repo inmemory/watched-repos.md.
External PRs that sit unanswered look unwelcoming. This skill is the first touch for every external pull request — it reads the diff, applies a structured rubric, posts a comment with a verdict + rationale, and labels the PR so a human reviewer can pick it up with full context. It is not a substitute for pr-review (depth) or auto-merge (execution); it is the welcoming layer that runs before either of those decide whether to engage.
Any PR whose author is not in the trusted set qualifies. The trusted set is, by precedence:
[bot] (dependabot[bot], renovate[bot], github-actions[bot], …) — these route to auto-merge / pr-review.aeonframework, aeonfun, and any login under a ## Trusted Authors heading in memory/watched-repos.md (same allowlist convention used by auto-merge).Everything else is external and gets triaged.
memory/watched-repos.md:
# Watched Repos
- aeonfun/aeon
- aaronjmars/aeon-agent
## Trusted Authors
- alice
- bob
If the file is missing and ${var} is empty, log PR_TRIAGE_OK no-watched-repos and exit.
Read memory/MEMORY.md for context.
Read memory/triaged-prs.json (if present; else treat as {}) — schema: {"owner/repo": [{"n": 143, "sha": "abc123", "at": "2026-04-29", "verdict": "ACCEPTED"}, ...]}. Used for idempotency keyed on (PR number, headRefOid).
Read the last 2 days of memory/logs/ as a fallback dedup signal in case the JSON state file is missing.
${var} matches ^[\w.-]+/[\w.-]+#\d+$ → single-PR mode: target that exact PR.${var} matches ^[\w.-]+/[\w.-]+$ → repo mode: scan all open PRs on that one repo.${var} is set but matches neither shape → abort with pr-triage: invalid var — expected owner/repo or owner/repo#N and exit.${var} is empty → fleet mode: read non-comment, non-blank - lines from memory/watched-repos.md (everything above the ## Trusted Authors heading).For each repo:
gh pr list -R owner/repo --state open --limit 25 \
--json number,title,body,author,isDraft,labels,headRefOid,baseRefName,additions,deletions,files,createdAt,updatedAt,isCrossRepository \
--search "created:>=$(date -u -d '14 days ago' +%Y-%m-%d)"
Per-run budget: ≤8 PRs per repo per run (newest first; remainder logged as overflow).
In single-PR mode, fetch just the one PR:
gh pr view N -R owner/repo \
--json number,title,body,author,isDraft,labels,headRefOid,baseRefName,additions,deletions,files,createdAt,updatedAt,isCrossRepository
Skip a PR if any of the following hold:
isDraft: true — drafts are work-in-progress^(WIP|\[WIP\]|Draft:) (case-insensitive)no-triage, do-not-merge, wip, blocked, triage:accepted, triage:needs-changes, triage:deferred, triage:out-of-scope (already triaged)(number, headRefOid) already appears in memory/triaged-prs.json["owner/repo"] (already triaged at this commit; new pushes re-triage)**Triage:** and was posted within the last 7 days (defensive layer in case state file is wiped). Check via:
gh api repos/owner/repo/issues/NUMBER/comments --jq '.[] | select(.body | startswith("**Triage:**")) | .created_at'
If every PR was skipped across all targets, log PR_TRIAGE_OK no-candidates and exit (no notification).
gh pr diff NUMBER -R owner/repo
If additions + deletions > 3000, do not read the full diff — read only the top-5 largest-delta files via:
gh api repos/owner/repo/pulls/NUMBER/files --jq 'sort_by(-(.additions + .deletions)) | .[0:5] | .[] | {path: .filename, patch}'
If gh pr diff fails entirely (e.g. mid-rebase) and the file API also returns empty, skip with reason empty-diff (do not block on transient API state).
Score the PR against four checks. Every check is observable from the diff + metadata, no guesswork.
| Check | Pass condition |
|---|---|
| Scope | Touches only skills/, docs/, output/, catalog/, README.md, CLAUDE.md. Touching .github/workflows/, aeon (root binary), bin/, scripts/, apps/mcp-server/, apps/dashboard/lib/ requires a maintainer. |
| Format | If a skills/<name>/SKILL.md is added or modified, the file has YAML frontmatter with name, description, var, tags keys. (Skip this check when no SKILL.md is touched.) |
| Originality | If a new skill is added, its directory name does not already exist on main. Cross-check via gh api repos/owner/repo/contents/skills once per run. |
| Size | additions + deletions ≤ 500 lines, OR labelled large-ok by a maintainer. |
Verdict assignment (first match wins, in this order):
.github/workflows/, aeon, scripts/prefetch-*, scripts/postprocess-*). External contributors cannot ship workflow / runtime changes; redirect them to file an issue.large-ok), OR PR is marked as RFC / proposal-only in the body, OR the PR depends on an external service that requires a secret the maintainer has not provisioned (mentions of *_API_KEY in added code without declaring it in the skill's requires:).pr-review to take a depth pass.Exactly one comment per (PR, headRefOid). Format must start with **Triage:** so the dedup check in step 3 finds it on the next run.
ACCEPTED:
**Triage:** ACCEPTED — clean against the contribution rubric (scope ✓ / format ✓ / originality ✓ / size ✓).
Thanks @author. A maintainer review pass will follow; in the meantime no changes requested from this triage layer.
NEEDS-CHANGES:
**Triage:** NEEDS-CHANGES — <one-line rubric reason>.
To proceed, please:
1. <specific actionable change>
2. <specific actionable change, if applicable>
Once updated, push to the same branch and this triage will re-run automatically.
DEFER:
**Triage:** DEFER — <one-line reason: size / RFC / external-secret / depends-on>.
This PR is sound but needs maintainer attention before it can move (reason above). Leaving open and labelled `triage:deferred`; @aaronjmars will pick it up on the next review pass.
OUT-OF-SCOPE:
**Triage:** OUT-OF-SCOPE — touches <protected path(s)> which external contributors cannot modify directly.
For changes here, please open an issue describing the goal and a maintainer will land the change. Closing-as-not-planned to keep the queue tidy; the issue is the right venue.
gh pr comment NUMBER -R owner/repo --body "<rendered comment>"
If gh pr comment returns Resource not accessible by integration, log PR_TRIAGE_NO_PERMISSION owner/repo#N once per run and continue with the next PR (do not abort; do not retry).
One label per verdict, all under the triage: namespace so they are easy to filter (gh pr list --label triage:accepted).
| Label | Color | Description |
|---|---|---|
triage:accepted | #0e8a16 | Passed first-touch rubric |
triage:needs-changes | #fbca04 | Author action required |
triage:deferred | #c5def5 | Sound but blocked on maintainer |
triage:out-of-scope | #e4e669 | Cannot land via external PR |
Wrap label creation so a missing label does not abort the whole run:
gh label create "triage:accepted" -R owner/repo --color "0e8a16" --description "Passed first-touch rubric" \
|| echo "PR_TRIAGE_LABEL_SKIPPED: triage:accepted (owner/repo)"
gh pr edit NUMBER -R owner/repo --add-label "triage:<verdict>" \
|| echo "PR_TRIAGE_LABEL_SKIPPED: pr=NUMBER"
Closing rule: only close on OUT-OF-SCOPE, and only when the protected-path violation is unambiguous (the PR touches .github/workflows/ or the root aeon binary).
gh pr close NUMBER -R owner/repo --reason "not planned" --comment "Closed as out-of-scope — see triage comment above. The right venue is a GitHub issue."
Never close on ACCEPTED, NEEDS-CHANGES, or DEFER. The point of this skill is to welcome contributors, not gatekeep them.
Append the triage record to memory/triaged-prs.json:
{
"aeonfun/aeon": [
{"n": 143, "sha": "abc1234", "at": "2026-04-29", "verdict": "ACCEPTED"},
{"n": 145, "sha": "def5678", "at": "2026-04-29", "verdict": "DEFER"}
]
}
Drop entries older than 90 days to keep the file bounded.
Send ./notify only if the run produced any:
OUT-OF-SCOPE (closing decision — operator should know in case the call was wrong)ACCEPTED PR from a first-time external contributor (cross-ref triaged-prs.json history; if the author has zero prior records, flag as first-PR welcome)For routine NEEDS-CHANGES / DEFER outcomes, the comment on the PR is the signal — no notify.
*PR Triage — ${today}*
Triaged N across M repos. Accepted: a, needs-changes: nc, deferred: d, out-of-scope: oos.
- owner/repo#143 — ACCEPTED (first PR by @newcomer): <title>
- owner/repo#150 — OUT-OF-SCOPE (touches .github/workflows): closed
If nothing matches the gate, no notification.
Append to memory/logs/${today}.md:
### pr-triage
- Mode: <single | repo | fleet>
- Repos: <list>
- Triaged: N (accepted=a, needs-changes=nc, deferred=d, out-of-scope=oos)
- First-PR welcomes: <comma-separated @logins, or "none">
- Closed (out-of-scope): <comma-separated URLs, or "none">
- Skipped: <count> (drafts=x, bots=y, trusted=z, already-triaged=w)
- Overflow (budget > 8): <repos with count, or "none">
- Source status: <per-repo: ok | fail — reason>
Terminal log lines:
PR_TRIAGE_OKPR_TRIAGE_ERROR source-status=<...> (no notification)gh unavailable entirely → PR_TRIAGE_ERROR gh-unavailable and exitUse gh CLI for all GitHub operations — it handles auth internally, so no bare $SECRET ever lands on the command line for the Bash permission layer to refuse. If gh errors at the repo level, record fail — <reason> in source status and skip that repo; do not abort the whole run. WebFetch cannot substitute for write operations (auth required); a fully unavailable gh is a hard exit.
gh pr list and gh pr view are PR-only.triage:* label per PR. New verdict on a re-run replaces the prior label.(PR, headRefOid) — a new push re-triages, an unchanged head does not.