Greenlight

Por Rene Turcios. Verificações pré-voo para contribuições open-source: esta issue é realmente implementável? Vereditos (GO / RISKY / TAKEN / GATED / STALE), pontuações de fricção do repositório e modo de varredura. CLI e servidor MCP com ferramentas check_issue, scan_repo, repo_friction.

Documentação

Greenlight

O Greenlight verifica uma issue do GitHub antes que você gaste horas nela e informa, em palavras simples, se o seu pull request provavelmente será aceito.

O problema

Você encontra uma issue que parece perfeita. Você programa a noite toda. Então uma destas coisas acontece:

  • Alguém já reivindicou o trabalho em um comentário. A issue ainda diz "não atribuída", mas três voluntários escreveram "eu fico com isso" há semanas e você nunca viu.
  • O repositório queria que você pedisse primeiro. Seu pull request é fechado porque os mantenedores exigem que contribuidores solicitem atribuição ou obtenham um aval (uma recomendação de alguém que conhecem) antes que qualquer pessoa possa abrir um PR, e ninguém te avisou.
  • Seus commits são rejeitados por um detalhe técnico. O repositório exige uma linha "Signed-off-by" em cada commit (chamada de assinatura DCO, abreviação de Developer Certificate of Origin) ou uma entrada na pasta de changelog, e você descobre isso depois de enviar.

Tudo isso são rituais de contribuição: regras não escritas que um repositório espera antes que um pull request externo conte. Cada repositório tem regras diferentes, e elas se escondem em lugares diferentes, desde arquivos CONTRIBUTING até arquivos de regras internas AGENTS.md (arquivos de instruções em linguagem simples que dizem a pessoas e agentes de codificação como trabalhar naquele repositório). Enfrentamos tudo isso manualmente ao avaliar issues reais, então o Greenlight automatiza a verificação.

O que o Greenlight faz

Um mecanismo, quatro passos simples:

  1. Verifique antes de reivindicar. Aponte para qualquer URL de issue. Ele lê a issue, seus comentários, pull requests vinculados e mencionados, e as regras do repositório, e então responde: GO (é seu para pegar), RISKY (possível, mas saiba disso primeiro), TAKEN (alguém está nisso), GATED (uma regra do repositório bloqueia você) ou STALE (abandonado). Ele também detecta trabalhos parcialmente reivindicados e issues onde metade da correção já foi enviada, para que você escopte o que resta.
  2. Reivindique do jeito certo. Ele redige o comentário de reivindicação na forma que as regras do repositório realmente querem: um simples "eu trabalho nisso" quando isso é suficiente, uma solicitação de atribuição quando o repositório exige uma, ou uma recusa quando um aval é necessário (nenhuma ferramenta pode dar aval por você). Ele nunca publica sem a sua autorização.
  3. Prepare seu espaço de trabalho com as regras do próprio repositório. Ele configura seu fork e branch e escreve uma lista de verificação que inclui o que aprendeu com o próprio repositório: os arquivos de regras internas, o comando de verificação que eles insistem, se o repositório quer uma entrada de changelog e como os commits são estilizados.
  4. Abra o PR somente quando o básico passar. Ele verifica se o branch está realmente à frente do repositório e, em repositórios que exigem assinatura DCO, verifica se cada commit tem a linha Signed-off-by antes de abrir o pull request.

Use quando

  • Você encontrou uma issue que gosta e está prestes a gastar tempo real nela.
  • Você quer saber se uma issue ainda é realmente sua para terminar, ou se alguém reivindicou silenciosamente parte dela em um comentário.
  • As regras de um repositório não estão claras e você quer vê-las resumidas antes de começar.
  • Você reivindicou algo há um tempo e quer saber se essa reivindicação ainda conta.
  • Você está escolhendo entre vários repositórios ou issues e quer o mais vencível primeiro.

O que faz, tecnicamente

Um mecanismo, quatro superfícies:

  1. Vereditos de disponibilidade para uma issue: GO, RISKY, TAKEN, GATED, STALE. Sinais: responsáveis, PRs vinculados abertos/fechados/mesclados (linha do tempo + busca + referências em comentários), heurísticas de comentários de reivindicação incluindo reivindicações escopadas (frases como "por favor atribua", "trabalhando nisso", "pegando a tarefa restante"), detecção parcialmente abordada (PRs mesclados que referenciam a issue, comentários de mantenedores como "metade abordada ... deixando aberto"), idade da issue e última atividade.
  2. Pontuações de fricção do repositório (0-100, 100 = mais fácil): portões de contribuição analisados de variantes de CONTRIBUTING mais arquivos de regras internas (AGENTS.md, CLAUDE.md), com cada portão registrando de qual arquivo sua evidência veio (atribuição-primeiro, aval, CLA, DCO, discussão-primeiro, comentário-primeiro, somente-colaboradores), mais sinais de resultado quando computáveis.
  3. Modo de varredura: classifique as issues abertas de boa-primeira-issue / ajuda-desejada de um repositório por veredito para que um contribuidor (ou agente) escolha uma vencível primeiro. Cai para issues abertas recentes não atribuídas quando um repositório não tem issues iniciais rotuladas.
  4. Automação de contribuição: comandos claim, prep e pr (mais ferramentas MCP correspondentes) que executam o pipeline após o veredito. Todas as escritas são dry-run por padrão e precisam de um token mais um sinalizador explícito de execução.

Um corpus de validação de dez casos reais da campanha (test/fixtures/cases/, executado por test/cases.test.ts) fixa cada regra de veredito a algo que realmente aconteceu: uma issue tomada, uma menção fraca de PR, portões de reivindicação-primeiro, portões de atribuição e aval, uma reivindicação escopada, uma issue meio enviada, um GO limpo e uma reivindicação obsoleta.

Instalação

npm install
npm run build

Defina GITHUB_TOKEN (um token de acesso pessoal clássico, sem escopos necessários para repositórios públicos) para aumentar o limite de taxa da API do GitHub de 60 para 5000 solicitações por hora. O Greenlight armazena em cache as respostas da API em ~/.cache/greenlight.

CLI

# Verdict for one issue
npx greenlight check https://github.com/batrapulkit/squidbrake/issues/74

# [GO] batrapulkit/squidbrake#74
#   Taint: tell the approver when an agent edits its own setup right after reading outside content
#   - open, unassigned, no linked PRs, no claim signals, no blocking gates

# Rank a repo's starter issues, GO first (falls back to recent open
# unassigned issues when the repo does not use those labels; --no-fallback to opt out)
npx greenlight scan PrefectHQ/fastmcp

# Friction score for a repo
npx greenlight friction triggerdotdev/trigger.dev

# JSON output for scripting
npx greenlight check <issue-url> --json

Exemplos reais da nossa avaliação:

  • batrapulkit/squidbrake#74 pontua GO: 0 comentários, rotulado ajuda-desejada, sem reivindicações, sem portões.
  • shadcn-labs/pdfcn#58 pontua RISKY (sinalizador reivindicado): um voluntário pediu atribuição no mesmo dia em que avaliamos.
  • langchain-ai/langchain#41185 pontua TAKEN (corrida de reivindicação): 3 reivindicantes fortes enquanto ainda "não atribuída".
  • PrefectHQ/fastmcp#5718 pontua GATED: FastMCP exige atribuição ou um rótulo "prs welcome" antes de um PR.
  • triggerdotdev/trigger.dev#5016 pontua GATED: PRs de autores sem aval são fechados automaticamente, uma solicitação de aval vem primeiro.

Como a pontuação funciona

O mecanismo de veredito é determinístico (sem LLM) e verifica, em ordem:

  1. Issue fechada: TAKEN (nunca aceitável).
  2. Qualquer responsável: TAKEN.
  3. Um PR vinculado aberto que fecha a issue: TAKEN. Um PR que apenas menciona o número da issue (como pdfcn PR #91, que fecha #70 mas lista issues irmãs no corpo) apenas adiciona um sinalizador weak-pr-mention e rebaixa um veredito de outra forma GO para RISKY.
  4. Dois ou mais reivindicantes fortes: TAKEN (corrida de reivindicação).
  5. Uma reivindicação forte recente de issue inteira (menos de 45 dias): RISKY com o sinalizador claimed. Uma reivindicação recente escopada a parte da issue ("pegando a tarefa restante"): RISKY com sinalizadores claimed + partial-claim e um motivo nomeando o reivindicante e o escopo, nunca TAKEN.
  6. Uma reivindicação forte com mais de 45 dias sem PR de fechamento: RISKY com o sinalizador stale_claim. O reivindicante provavelmente desistiu, mas ninguém sabe ao certo. Reivindicações escopadas obsoletas recebem o mesmo tratamento.
  7. Um portão rígido (atribuição, aval, somente-colaboradores) sem ninguém atribuído: GATED.
  8. Sem atividade por 180+ dias: STALE.
  9. Um portão suave de reivindicação-primeiro (o repositório pede que contribuidores comentem antes de começar, como pdfcn): nunca GATED; limita um veredito de outra forma GO a RISKY com uma nota, o mesmo formato de rebaixamento de uma menção fraca de PR.
  10. Caso contrário: GO.
  11. Um PR aberto referenciado em um comentário de não autor cujo título/corpo menciona o número da issue: rebaixa um veredito de outra forma GO para RISKY com o sinalizador comment-mentioned-pr ("pode já cobrir parte desta issue"). Nenhum pode produzir TAKEN; apenas PRs de fechamento fazem isso.
  12. Parcialmente abordada: PRs mesclados que referenciam o número da issue (mencionados em comentários ou vinculados), ou comentários de mantenedores sinalizando que parte do trabalho já foi enviada ("Metade abordada por #905, deixando aberto para a metade B", "Enviado na v3.1.0" ao lado da referência da issue). Um GO simples esconde o trabalho de escopo que isso precisa, então o sinalizador partially-addressed é adicionado, um veredito de outra forma GO é limitado a RISKY com um motivo como "parte desta issue já foi enviada (PR #905, mesclado); escope seu trabalho para o que resta". Nunca TAKEN.

A detecção de reivindicação varre comentários por frases explícitas de reivindicação, sinais de progresso ("correção pronta", "PR a caminho", "abri um PR") e ofertas suaves ("feliz em corrigir"). Autores de bots são ignorados, assim como relatores de issues, a menos que anunciem uma correção pronta. Reivindicações escopadas ("pegando a tarefa restante", "reivindicando esta metade") são registradas como parciais: uma reivindicação parcial recente rebaixa um veredito de outra forma GO para RISKY com um motivo nomeando o reivindicante e o escopo, nunca TAKEN. Referências de PR (#NNN) em comentários de não autores são verificadas cruzadamente com a API de PR: um PR aberto referenciado que menciona a issue rebaixa GO para RISKY com o sinalizador comment-mentioned-pr, e um mesclado alimenta a regra 12 acima.

A pontuação de fricção começa em 100 e subtrai pesos de portões (atribuição -25, aval -35, somente-colaboradores -50, discussão-primeiro -10, reivindicação-primeiro -5, CLA/DCO -5 cada), ajusta pela taxa de mesclagem de PRs externos e tempos de revisão/resposta quando computáveis, e adiciona até +10 para boas-primeiras-issues abertas. Sinais desconhecidos permanecem nulos e são ignorados, nunca adivinhados. Veja src/friction.ts para a fórmula exata.

Servidor MCP

O mesmo mecanismo é exposto via stdio para agentes de codificação (Claude, Cursor, Cline). A vantagem: agentes desperdiçam mais tokens corrigindo issues já tomadas. Faça o agente verificar a issue antes de escrever código.

{
  "mcpServers": {
    "greenlight": {
      "command": "node",
      "args": ["/path/to/greenlight/dist/index.js"],
      "env": { "GITHUB_TOKEN": "your-token" }
    }
  }
}

Ferramentas:

  • check_issue - veredito para uma URL de issue
  • scan_repo - classifique as issues abertas de um repositório, GO primeiro (issues iniciais rotuladas, caindo para issues abertas recentes não atribuídas)
  • repo_friction - pontuação de fricção para um repositório
  • claim_issue - comentário de reivindicação com veredito (dry run a menos que execute: true)
  • prep_issue - verificação de fork e branch mais uma lista de verificação local PREP.md com as convenções aprendidas do repositório (dry run a menos que execute: true)
  • open_pr - abertura de PR ciente de DCO a partir de um branch de fork (dry run a menos que execute: true)

Execute localmente: npm run dev (entrada MCP é src/index.ts; CLI é src/cli.ts).

Automação

O Greenlight 0.2.0 automatiza o pipeline de contribuição que seu autor executou manualmente para quatro PRs reais (shadcn-labs/pdfcn #92-#95): veredito, comentário de reivindicação, fork branch e abertura do PR, com consciência de DCO em todo o processo.

# 1. Claim the issue: verdict first, comment shaped by the repo's gates
greenlight claim https://github.com/shadcn-labs/pdfcn/issues/65

# 2. Prepare: fork/branch check (learning the repo's branch convention) plus a PREP.md checklist
greenlight prep https://github.com/shadcn-labs/pdfcn/issues/65 --dir /tmp/prep65

# 3. Open the PR from your fork branch (verifies DCO sign-off on DCO repos)
greenlight pr https://github.com/shadcn-labs/pdfcn/issues/65 --branch feat/quarterly-report-block

Padrões de segurança, e isso é um recurso:

  • Dry run por padrão. Todos os três comandos imprimem exatamente o que iriam publicar ou criar e saem. Nada é publicado ou criado sem --yes (CLI) ou execute: true (MCP).
  • Escritas precisam de um token. Operações de leitura funcionam sem token algum. Operações de escrita exigem GITHUB_TOKEN (ou GH_TOKEN); sem um, imprimem um erro claro nomeando a variável de ambiente e saem com código não zero.
  • Limitado por veredito. claim recusa vereditos TAKEN ou STALE a menos que --force, e recusa repositórios com portão de aval diretamente (um aval não pode ser automatizado). Repositórios com portão de atribuição recebem uma solicitação de atribuição em vez de um comentário de intenção; repositórios de reivindicação-primeiro (comentar antes de começar) recebem o comentário de intenção padrão, que satisfaz o ritual.
  • Nomes de branch cientes do repositório. prep lê os branches principais de PRs fechados recentes e segue uma convenção dominante (o feat/<slug>-block do pdfcn) enquanto ainda mostra o padrão feat/<slug>-<number>.
  • Ciente de DCO. Em repositórios DCO, pr verifica se cada commit no branch carrega uma linha Signed-off-by: e recusa, listando os commits não assinados, quando um está faltando.
  • Preparação ciente do repositório. prep também aprende os rituais de contribuição do repositório para a lista de verificação PREP.md: quais arquivos de regras internas existem, o comando de verificação que eles insistem (como pnpm verify), se o repositório monta seu changelog a partir de um diretório .changes/, quais scripts de package.json raiz existem e se commits recentes seguem Conventional Commits. Regras vinculantes vivem cada vez mais em AGENTS.md em vez de CONTRIBUTING, e a preparação lê essas também.

O índice de fricção

data/friction-index.json é um conjunto de dados verificado e crescente de repositórios pontuados. Começa com o ecossistema MCP/AI que avaliamos manualmente em 2026-10-13 (FastMCP, trigger.dev, langchain, deepagents, openclaw, squidbrake, reticle, pdfcn, chatflow-agent e os três repositórios de SDK MCP). Regere-o com npm run index. Entradas rotuladas como hand-verified 2026-10-13 vêm da leitura manual das políticas reais dos repositórios e dos rastreadores de issues. Entradas rotuladas como live foram extraídas de arquivos de regras internas ao vivo (variantes de CONTRIBUTING, AGENTS.md, CLAUDE.md). Cada portão registra de qual arquivo suas evidências vieram. Os campos de resultado calculados (taxas de merge, tempos de revisão) permanecem null até que possamos calculá-los honestamente, nunca fabricados.

Desenvolvimento

npm test    # tsx --test, includes fixture tests that reproduce our real verdicts
npm run build

Roadmap (Futuro)

  • Extensão de navegador que pontua issues inline no github.com
  • Painel hospedado do índice de fricção, atualizado em um cronograma
  • GitHub Action para mantenedores que rotula automaticamente comentários de reivindicação
  • Detecção de correções estacionadas e lembretes automáticos: escanear forks em busca de branches que referenciam issues abertas e lembrar quando o portão for satisfeito

Licença

MIT. Veja LICENSE.