GitHub Triage
Faça a triagem das issues e pull requests abertos de um repositório GitHub. Opcionalmente, limpe PRs prontos primeiro (mesclar PRs de bots aprovados e PRs aprovados por mantenedores, revisar os nunca revisados), depois feche issues que já estão resolvidas (com um comentário citando o PR ou commit que as resolveu), garanta que as issues e os PRs pendentes que as corrigem façam referência uns aos outros e atribua uma estimativa local apenas de prioridade e tamanho de mudança para cada issue que ainda está pendente.
Quando Usar
- Quando o usuário executar
/github-triagepara limpar ou revisar as issues e pull requests abertos de um repositório. - Quando um backlog de issues se desviou: trabalho resolvido deixado em aberto, correções que chegaram sem fechar suas issues, ou PRs em andamento que nunca vincularam sua issue.
- Quando PRs prontos se acumularam (bumps de dependência aprovados, PRs aprovados e verdes) ou PRs estão parados sem revisão.
Quando NÃO Usar
- Não invoque automaticamente. Esta skill realiza escritas irreversíveis no GitHub (mesclar PRs, fechar issues, postar comentários) e é executada apenas por invocação explícita.
- Não use para aplicar labels de prioridade/esforço no GitHub. Prioridade e tamanho são apresentados apenas localmente e nunca são postados (veja Regras de Segurança).
- Não use como substituto para a decisão final de mesclagem de um humano — cada mesclagem é proposta para aprovação explícita, nunca executada autonomamente.
Princípios Fundamentais
- Escritas são protegidas. Calcule a triagem completa primeiro, apresente cada escrita proposta — incluindo mesclagens — para revisão, e não execute nada até que o usuário aprove.
- Evidência antes de fechar. Nunca feche uma issue sem uma razão concreta e citada (um PR mesclado ou um commit no branch padrão). Quando a evidência for fraca ou ambígua, deixe a issue pendente e sinalize para revisão.
- Prioridade e tamanho ficam locais. São uma ferramenta de planejamento interna para o usuário, nunca escrita no GitHub.
Fluxo de Trabalho
Fase 0: Selecionar o repositório alvo
gh auth status # confirmar se gh está autenticado
git rev-parse --is-inside-work-tree # o diretório atual é um repositório git?
git remote -v # enumerar remotos
Determine o conjunto de repositórios distintos hospedados no GitHub entre os remotos.
Um remoto é hospedado no GitHub quando sua URL tem o host github.com, em qualquer uma destas formas:
https://github.com/OWNER/REPO(.git)[email protected]:OWNER/REPO(.git)ssh://[email protected]:OWNER/REPO(.git)
Normalize cada um para OWNER/REPO e deduplique (uma configuração de fork pode ter origin
e upstream apontando para repositórios GitHub diferentes; vários remotos apontando para o
mesmo OWNER/REPO contam como um).
Regra de seleção:
| Situação | Ação |
|---|---|
| Exatamente um repositório GitHub distinto | Use-o como padrão — não pergunte. |
| Não é um repositório git, ou zero remotos GitHub | Peça ao usuário o OWNER/REPO para fazer a triagem. |
| Mais de um repositório GitHub distinto | Use AskUserQuestion para deixar o usuário escolher qual OWNER/REPO. |
Instâncias do GitHub Enterprise não podem ser detectadas automaticamente de forma confiável. Se o usuário trabalhar em uma instância GHE, peça o
OWNER/REPOe peça para ele definirGH_HOST/ usar o host configurado dogh. Confirme o repositório resolvido de volta ao usuário antes de continuar.
Armazene o resultado como REPO="OWNER/REPO" e passe -R "$REPO" para cada chamada gh.
Valide-o com ^[A-Za-z0-9._-]+/[A-Za-z0-9._-]+$ antes do uso, para que uma URL remota malformada ou
hostil nunca flua para um comando.
Fase 1: Coletar issues e contexto
# Issues abertas (gh issue list exclui PRs por padrão)
gh issue list -R "$REPO" --state open --limit 1000 \
--json number,title,body,labels,assignees,comments,reactionGroups,createdAt,updatedAt,url
# PRs abertos — candidatos para "correção pendente" (fase de issues) e triagem de PRs (Fase 2)
gh pr list -R "$REPO" --state open --limit 1000 \
--json number,title,body,author,isDraft,reviewDecision,latestReviews,\
mergeable,mergeStateStatus,statusCheckRollup,labels,createdAt,headRefName,url,closingIssuesReferences
# PRs mesclados recentemente — candidatos para "já resolvido"
gh pr list -R "$REPO" --state merged --limit 300 \
--json number,title,body,mergedAt,url,closingIssuesReferences
closingIssuesReferences lista as issues que um PR está vinculado a fechar — preenchido por qualquer
uma das palavras-chave de fechamento do GitHub (close/closes/closed, fix/fixes/fixed,
resolve/resolves/resolved) no corpo do PR, ou por um link manual da interface. É o sinal
mais forte disponível. Para issues que ele não cobre, pesquise também mensagens de commit no branch
padrão. Resolva o branch padrão de forma autoritativa a partir do repositório selecionado (não do
origin/HEAD local, que pode não estar definido ou apontar para o remoto errado):
default_branch=$(gh repo view "$REPO" --json defaultBranchRef --jq .defaultBranchRef.name)
# Ancore o número da issue para que #12 não corresponda a #120, #123, …
git log --oneline "origin/$default_branch" \
| grep -iE "(close|fix|resolve)[sd]? +#<N>([^0-9]|$)"
Fase 2: Triar pull requests abertos (opcional)
Manipule PRs antes das issues: mesclar PRs prontos aqui significa que a verificação "já resolvido" na fase de issues verá o trabalho que essas mesclagens acabaram de fazer.
Se não houver PRs abertos, pule esta fase. Caso contrário, resuma os PRs abertos e pergunte ao usuário se deseja lidar com os PRs agora (AskUserQuestion: lidar com PRs / pular para issues). Se ele pular, vá direto para a classificação de issues.
Classifique cada PR aberto com base em seu estado de revisão, CI e mesclagem. Os formatos de campo abaixo são
o que gh pr ... --json realmente retorna — confie neles, não na intuição:
- Pronto para mesclar =
mergeable == "MERGEABLE"emergeStateStatus == "CLEAN"e CI não está bloqueando (abaixo).CLEANé o veredito do lado do servidor do GitHub "sem conflitos, não atrás, não é rascunho, verificações necessárias verdes" — qualquer outromergeStateStatus(BEHIND,UNSTABLE,BLOCKED,DIRTY,DRAFT, …) não está pronto. Tratemergeable == "UNKNOWN"(o GitHub recalcula a capacidade de mesclagem preguiçosamente, especialmente logo após outra mesclagem) como não pronto — repolhe brevemente ou pule; nunca mescle com base nele. - CI não bloqueando — escaneie
statusCheckRollup(chaveado por__typename) e rejeite o PR apenas em um problema real: uma falha grave (umCheckRuncujaconclusionéFAILURE/CANCELLED/TIMED_OUT/ACTION_REQUIRED/STARTUP_FAILURE/STALE, ou umStatusContextcujostateéFAILURE/ERROR), ou qualquer coisa ainda em execução (umCheckRuncomstatusQUEUED/IN_PROGRESS/WAITING/PENDING, ou umStatusContextcomstatePENDING/EXPECTED— espere, não mescle ainda).SUCCESS,NEUTRALeSKIPPEDsão ok e não devem bloquear (por exemplo, uma execução CodeQL que relataNEUTRALem um bump de dependência — um PR verde do Dependabot éCLEANcom uma verificação CodeQLNEUTRAL). Um rollup vazio é nenhum CI — um estado distinto, nunca tratado como pronto.mergeStateStatus == "CLEAN"já reflete o status de verificações necessárias; use o rollup para capturar falhas/pendentes em verificações não necessárias. - Bot/automatizado =
author.is_bot == true. Compare a lista de permissões de mesclagem automática comauthor.loginapós normalizar a renderização dogh— remova umapp/inicial e um[bot]final (o gh retorna Dependabot comoapp/dependabotem algumas versões edependabot[bot]em outras; normalize ambos paradependabot). Permitidos por padrão:dependabot,renovate, mais qualquer um que o usuário nomear. Um PR aprovado de um bot não permitido é relatado, nunca oferecido para mesclagem. - Aprovado por mantenedor =
latestReviewstem uma entrada comstate == "APPROVED"cujoauthorAssociationéOWNER/MEMBER/COLLABORATORe cujoauthor.loginnão é o autor do PR. Não usereviewDecision == "APPROVED"sozinho: ele é orientado por proteção de branch e énullem repositórios sem regra de revisão necessária, então tanto superestima (não confirma acesso de escrita) quanto perde aprovações genuínas. - Nunca revisado =
latestReviewsnão tem nenhuma entradaAPPROVED/CHANGES_REQUESTEDde ninguém além do autor do PR (um comentário de bot de fork "revisão desabilitada" não é revisão).
| Categoria | Condição | Ação oferecida |
|---|---|---|
| PR de bot mesclável | bot permitido + pronto + não rascunho | Oferecer mesclagem incremental, em ordem |
| Aprovado e pronto | aprovado por mantenedor + pronto + não rascunho | Solicitar mesclagem |
| Nunca revisado | não bot + apenas o autor revisou (ou nenhuma revisão) + não rascunho | Oferecer criar um subagente de revisão |
| Precisa de trabalho | rascunho, falha grave de CI, CI pendente, conflitos, atrás, alterações solicitadas, ou um PR de bot que não está pronto | Apenas relatar — nenhuma ação oferecida |
("pronto" já inclui CI não bloqueando. Subagentes de revisão são para PRs de autoria humana — um bump de dependência de bot que não está pronto é relatado como Precisa de trabalho, não revisado.)
Apresente os PRs categorizados e ofereça as ações aplicáveis via AskUserQuestion.
Mesclagem incremental, em ordem (PRs de bot e PRs aprovados-prontos): confirme o conjunto de mesclagem e o método de mesclagem primeiro (mesclar é irreversível), então mescle um de cada vez, do mais antigo ao mais novo. Escolha um método que o repositório permita e falhe fechado se não permitir:
gh repo view "$REPO" --json mergeCommitAllowed,squashMergeAllowed,rebaseMergeAllowed # repositório posicional, não -R
Para cada PR na ordem, reverifique imediatamente antes de mesclar (o estado muda após cada
mesclagem — um PR que chegou pode deixar o próximo BEHIND, conflitante, ou recalculando), mescle
sincronamente, então confirme que ele chegou antes de avançar:
gh pr view <N> -R "$REPO" --json isDraft,reviewDecision,mergeable,mergeStateStatus,statusCheckRollup
# prossiga apenas se ainda estiver pronto: não rascunho, mergeable == MERGEABLE, mergeStateStatus == CLEAN, CI não bloqueando
gh pr merge <N> -R "$REPO" --<método> # nunca --auto, nunca --admin
gh pr view <N> -R "$REPO" --json state # espere "MERGED" antes de ir para o próximo PR
Pare e relate se um PR não estiver mais pronto (incluindo mergeable == "UNKNOWN"), se a
mesclagem não ocorreu, ou se qualquer verificação necessária não está verde — nunca force, --admin,
--auto, ou pule uma verificação. Para PRs de bot, mostre a dependência e o salto de versão (por exemplo,
bumps major) na proteção para que o usuário possa decidir com contexto.
Subagentes de revisão (PRs nunca revisados): quando o usuário optar, crie um Agente
por PR — todos em uma única mensagem do assistente para que executem em paralelo. Cada subagente
revisa o diff de um PR e retorna uma revisão estruturada; escreva cada uma em
github-pr-<número>-review.md no diretório de trabalho (sobrescrevendo qualquer arquivo anterior
para aquele PR). As revisões são somente leitura e nunca postadas no GitHub. Veja
references/reviewing-prs.md para o prompt do subagente,
rubrica de revisão e formato do arquivo.
Após quaisquer mesclagens, obtenha novamente a lista de PRs mesclados (a consulta --state merged
da Fase 1) para que a fase de issues possa detectar issues que essas mesclagens resolveram.
Fase 3: Classificar cada issue aberta
Classifique cada issue aberta em exatamente um bucket.
Bucket A — Já resolvida (o trabalho chegou, a issue foi deixada em aberto). Requer evidência concreta; prefira corroboração sobre um único sinal fraco:
- Um PR mesclado lista a issue em
closingIssuesReferences, ou seu título/corpo referencia#Njunto com uma palavra-chave de fechamento. (Mais forte.) - Um commit no branch padrão referencia
#Ncom uma palavra-chave de fechamento. - O comportamento que a issue pede existe no código atual — verifique lendo o código relevante com Grep/Read, não assuma. Uma implementação diferente ou parcial não resolve a issue.
→ Escrita proposta: fechar a issue com um comentário que nomeia o PR/commit resolvedor.
gh issue close <N> -R "$REPO" \
-c "Resolvido por #<PR> (<motivo curto>). Fechando, pois a mudança agora está em $default_branch."
Bucket B — PR pendente a resolveria (um PR aberto aborda a issue).
Detecção em qualquer direção: o closingIssuesReferences do PR aberto inclui a
issue; o corpo/comentários da issue vinculam o PR; ou um PR aberto claramente corrige a
mesma coisa que a issue descreve. O objetivo é que a issue e o PR façam referência
um ao outro — preencha apenas lacunas genuínas, e prefira escritas não destrutivas:
- Nenhuma referência em nenhuma direção → poste um comentário apontando (não destrutivo) no
lado que não tem. Uma menção de
#<PR>/#<N>cria uma referência cruzada que o GitHub espelha na linha do tempo do outro.gh issue comment <N> -R "$REPO" -b "Uma correção está em andamento em #<PR>." - Já vinculado em pelo menos uma direção → registre "já vinculado — nenhuma ação".
Não edite o corpo do PR a menos que o usuário explicitamente queira que o PR feche automaticamente a issue na mesclagem. Um comentário estabelece uma referência, mas não dispara o fechamento automático — apenas uma palavra-chave de fechamento no corpo do PR ou em uma mensagem de commit o faz. Quando o usuário optar, nunca sobrescreva a descrição: obtenha o corpo novamente imediatamente antes de editar e passe via stdin, para que o texto não confiável do PR nunca transite por uma string interpolada por shell:
body=$(gh pr view <PR> -R "$REPO" --json body --jq .body)
printf '%s\n\nCloses #%s\n' "$body" "<N>" | gh pr edit <PR> -R "$REPO" --body-file -
Não duplique links que já existem.
Bucket C — Pendente (sem resolução, sem PR pendente). Atribua, apenas localmente, uma prioridade e uma estimativa de tamanho de mudança (próxima seção).
Fase 4: Pontuar issues pendentes (APENAS LOCAL)
Prioridade — Crítico / Alto / Médio / Baixo. Considere:
- Impacto / gravidade — bugs de segurança, perda de dados, travamento ou correção estão acima de
melhorias; docs/cosmético estão no nível mais baixo. Labels existentes (
security,bug,crash,regression) são sinais fortes. - Alcance — quantos usuários/fluxos de trabalho são afetados.
- Sinal — reações (👍), relatos duplicados, idade com atividade contínua.
- Urgência — bloqueia um lançamento, tem um prazo, ou tem uma regressão ativa.
Tamanho da mudança — a proxy de esforço, expressa como um balde de camiseta size/* a partir
das linhas totais alteradas estimadas (adições + exclusões, ignorando arquivos gerados/fornecidos),
usando o padrão de limites do Kubernetes/Prow:
Fase 5: Apresentar relatório final e aguardar aprovação
Após a triagem, resuma em um único relatório:
- Resolvidas — issues que serão fechadas.
- Vinculadas — issues agora vinculadas a PRs de correção.
- Pontuação local — prioridade e tamanho para issues pendentes.
- Mesclagens de PR — PRs que serão mesclados.
- Revisões de PR — PRs que serão revisados.
Pergunte ao usuário se ele confirma a execução de todas as escritas propostas. Se ele negar, pare. Se aprovar, execute cada escrita. Para mesclagens, execute uma de cada vez com reverificação. Para subagentes de revisão, crie-os em paralelo. Para fechamentos de issues e comentários, execute em lote.
Parabenize o usuário pela triagem concluída e resuma o estado final do repositório.
Estrutura da Skill
Variáveis de Ambiente
$GITHUB_TOKENough auth status— autenticação, obrigatório.$GH_HOST— host personalizado do GitHub (para GHE), opcional.
Arquivos
references/reviewing-prs.md— prompt do subagente para revisão de PRs.github-pr-<número>-review.md— saída das revisões dos subagentes.
Regras de Segurança
- Nunca mescle um PR sem confirmar que ainda está pronto imediatamente antes da mesclagem.
- Nunca force mesclagem ou use
--admin/--auto. - Nunca escreva prioridade ou tamanho no GitHub.
- Nunca feche uma issue sem uma evidência citada.
- Execute apenas por invocação explícita do usuário.
Exemplo de Uso
# O usuário invoca a skill
/github-triage
# A skill detecta o repositório, coleta dados, classifica e propõe ações.
# O usuário confirma, e a skill executa as escritas propostas.