Pular para conteúdo

AUR-451 — O review de pull request passa a usar o motor inteiro

Documento histórico do board. Pode descrever componentes removidos; para uso atual, consulte o guia do produto.

O defeito medido (revisao de produto 2026-08-14)

cmd/aurumcode/pr.go nunca chamava SecurityScan, e das flags do comando so usava countAtOrAbove internamente para sustentar --check. No caminho de pull request -- o caso de uso principal do produto -- --seguranca/--fail-on/--limite/--modelo eram aceitas como flags mas nao faziam nada: sem varredura de seguranca, sem gate de severidade, sem teto de custo, sem escolha de modelo. O comentario do proprio pr.go declarava isso como Non-goal do card que o criou (AUR-438). Este card remove essa limitacao.

O que este card entrega

aurumcode review --pr <numero> --repo <dono>/<projeto> --publicar --na-linha \
  [--seguranca] [--fail-on <nivel>] [--limite <usd>] [--modelo <nome>]

As quatro capacidades que ja funcionavam em --base agora valem em --pr, reutilizando exatamente as mesmas funcoes que o caminho --base ja chama (cmd/aurumcode/main.go, cmd/aurumcode/cost.go) -- nenhuma logica foi duplicada ou reimplementada:

  • --seguranca: roda review.SecurityScanWithCoverage sobre o diff do pull request -- o mesmo pacote/funcao que --base ja usa -- e imprime a mesma nota de cobertura do AUR-450 em stderr (security pass applied N of M security rules (...)). Cada achado de seguranca vira seu proprio comentario no pull request, publicado exatamente como um achado de qualidade: na linha exata quando o diff adicionou aquela linha, geral caso contrario (a classificacao do AUR-438, isInlineEligible, que este card nao altera). O comentario carrega a citacao da regra ((rule security/<id>: <titulo>)) porque Message ja chega assim de review.enforceRuleCitations -- nao ha uma secao separada como no relatorio stdout de --base, porque o formato de saida de --pr sempre foi "um comentario por achado", nao um relatorio de texto.
  • --fail-on <nivel>: apos a publicacao, o comando sai com o mesmo codigo distinto exitFindings (3) que --base ja usa quando algum achado publicado -- de qualidade ou de seguranca -- fica no limiar escolhido ou acima (severityRank/countAtOrAbove, inalterados). E independente do gate proprio de --check (grave-only, AUR-439): qualquer um dos dois fecha o portao sozinho.
  • --limite <usd>: o mesmo gate de custo do AUR-433 (internal/llm/cost.Tracker, buildCostTracker, fixedModelProvider) estima o custo antes de chamar o modelo e recusa -- sem gastar nada -- quando a estimativa excede o teto, reportando a estimativa e, em caso de sucesso, o custo real em stderr. A recusa acontece antes de qualquer comentario ser publicado.
  • --modelo <nome>: selectProviderForModel, o mesmo mecanismo de --base, escolhe o provider; quando o modelo pedido nao pode ser servido, reportModelUnavailable falha alto (exit 1), nunca um review vazio com exit 0.

Sem nenhuma das quatro flags novas, --pr e byte-identico ao contrato ja publicado pelo AUR-438/AUR-439 -- provado por sha256 contra um binario compilado do commit pai (antes deste card), nao so por leitura de codigo (ver "Prova de compatibilidade" abaixo).

Ordem de validacao

A validacao de --fail-on/--modelo/--limite acontece antes da checagem de permissao de escrita, da busca do diff e de qualquer chamada ao modelo -- a mesma ordem que --base ja segue, e pelo mesmo motivo: um nivel de --fail-on desconhecido, um --modelo vazio ou um --limite vazio/nao numerico e erro de uso (exit 2), nunca um gate silenciosamente desabilitado, e nunca vale a pena gastar uma chamada de rede para descobrir isso.

Onde a seguranca entra na publicacao

runPRReview combina result.Issues (achados de qualidade) com os achados de seguranca num unico slice antes de sortedIssues -- a mesma ordenacao (arquivo, linha) que ja rege a sequencia de publicacao do AUR-438. Um achado de qualidade e um achado de seguranca na mesma linha publicam dois comentarios distintos, nenhum e descartado nem mesclado no outro.

Ordem de prioridade se o escopo precisasse ser cortado

O card declarou esta ordem de valor; todas as quatro foram entregues, mas fica registrada porque orientou o desenho:

  1. --seguranca com --pr (o caso de uso que vende o produto).
  2. --fail-on com --pr (o gate de CI passa a considerar severidade).
  3. --limite com --pr (nao gastar sem teto no caminho automatico).
  4. --modelo com --pr.

Prova de compatibilidade (sha256 contra o binario do commit pai)

Como parte da validacao deste card, o binario atual (cmd/aurumcode com este card integrado) e o binario compilado do commit pai (git show HEAD:cmd/aurumcode/{main,pr}.go, antes deste card) foram executados com o comando review --pr 42 --repo dono/projeto --publicar --na-linha -- sem nenhuma das quatro flags novas -- contra o mesmo fake GitHub e a mesma resposta de modelo deterministica. stdout e stderr sao byte a byte identicos entre os dois binarios (mesmo sha256), confirmando que o comando publicado antes deste card nao mudou nenhum byte.

Exit codes

Inalterados: o mesmo vocabulario que --base e --pr ja publicavam.

  • 0: os achados foram publicados (ou "No issues found."), sem erro, e (quando --fail-on foi dado) nenhum achado publicado atingiu o limiar.
  • 1: falha em tempo de execucao -- busca do diff, chamada ao modelo, recusa por falta de permissao de escrita, falha ao publicar um comentario especifico, --modelo indisponivel, ou --limite estourado (nada foi gasto).
  • 2: erro de uso -- inclui agora um --fail-on desconhecido, um --modelo vazio, ou um --limite vazio/nao numerico/nao positivo em --pr, exatamente como --base ja recusa.
  • 3 (exitFindings): pelo menos um achado publicado -- de qualidade ou de seguranca -- ficou no limiar de --fail-on ou acima. Novo neste card para o caminho de PR; o mesmo codigo que --check e --base ja usam para o mesmo significado.

Exemplo executavel sem segredo

bash tests/e2e/AUR-451.sh E2EAUR451

Compila o binario real, sobe um fake GitHub em loopback a partir de tests/fixtures/scm/github/ (permissoes de leitura-escrita e so-leitura, resposta de comentario criado) servindo um diff que este script constroi -- tests/fixtures/scm/github/pr-42.diff e um read_path, nao editavel por este card, e nao contem nada que uma regra de seguranca do catalogo combine -- plantando API_KEY=AURUM-FAKE-KEY-9000-2222 (o mesmo valor sintetico que tests/unit/AUR-442.go ja prova bater com security/hardcoded-secret) na linha adicionada de cmdb/settings.go. Roda aurumcode review --pr 42 --repo dono/projeto --publicar --na-linha --seguranca --fail-on high contra ele. Prova: o achado plantado chega como comentario inline citando security/hardcoded-secret; o comando sai com 3; repetir a execucao produz a mesma saida; --seguranca sozinho (sem --fail-on) ainda publica o achado mas sai com 0; sem nenhuma flag nova o mesmo diff nao publica nada (No issues found., prova de que a correcao e aditiva); --limite 0.0001 recusa antes de qualquer publicacao; --modelo local sem provider configurado falha alto; um token so-leitura continua recusado antes de qualquer busca ou publicacao.

Selectors e exit codes do aceite

  • Aceite: tests/acceptance/AUR-451.sh -- selectors AC-001 (tudo), TestAUR451, IntegrationAUR451, E2EAUR451, AC-001-MUT-001.
  • Exit codes (convencao do board, tests/acceptance/EXIT_CODE_CONVENTION.md): 0 comportamento provado; 1 RED comportamental; 64 selector desconhecido; 79 infraestrutura / inconclusivo (nunca evidencia de RED).

Nota de nomenclatura de selector (a mesma tecnica que tests/unit/AUR-442.go, tests/unit/AUR-449.go e tests/unit/AUR-450.go ja documentam): o texto do card nomeia TestAUR435/IntegrationAUR435/E2EAUR435 na secao TDD proof, um artefato de copia-e-cola do card AUR-435 usado como base de redacao. Esses simbolos ja existem em seus pacotes (tests/unit/AUR-435.go, tests/integration/AUR-435.go), entao as provas deste card sao TestAUR451/IntegrationAUR451/E2EAUR451.

MUT-001

Mutacao: em uma copia gravavel de cmd/aurumcode/pr.go, a linha result.Issues = combined -- o unico ponto onde os achados de seguranca entram na lista publicada como comentarios -- e substituida por um no-op. --seguranca continua sendo aceita e validada como flag, a nota de cobertura do AUR-450 continua imprimindo em stderr, mas nenhum achado de seguranca chega a virar comentario: exatamente o defeito medido que este card corrige. Sob a mutacao, o cenario AC-001 (--seguranca --fail-on high sobre o diff com o segredo plantado) nao encontra nenhum achado a publicar, cai no ramo pre-existente "No issues found." e sai com 0 em vez de 3 -- tests/e2e/AUR-451.sh rejeita isso (ac001_wrong_exit/ac001_missing_finding_line/etc.). A fonte versionada nunca e tocada; a restauracao roda a mesma prova contra o binario nao mutado e reproduz o GREEN exato.

Diagnostico de falha

  • AUR-451/AC-001/behavior-missing: o caminho de PR nao entrega nenhuma das quatro capacidades.
  • ac001_missing_finding_line / ac001_missing_rule_citation / ac001_missing_inline_marker / ac001_wrong_post_count: o achado de seguranca plantado nao foi publicado -- o defeito medido, ou uma regressao equivalente.
  • ac001_wrong_exit: o gate --fail-on nao fechou sobre o achado grave de seguranca (ou fechou quando nao devia). limite_missing_refusal / limite_post_leaked: --limite nao recusou antes de publicar, ou recusou tarde demais (algo ja tinha sido postado).
  • modelo_missing_message: --modelo indisponivel nao falhou com a mensagem esperada de reportModelUnavailable.
  • readonly_not_refused / readonly_post_leaked: a recusa de publicacao sem permissao de escrita (AUR-437/AUR-438, inalterada por este card) foi violada.
  • non_deterministic: duas execucoes identicas divergiram.
  • infrastructure/missing_go, infrastructure/mktemp, infrastructure/fakegithub_did_not_start (exit 79): ambiente, nunca RED.

Compatibility, migration, rollback

  • Compatibility: sem as quatro flags novas, --pr ... --publicar --na-linha e byte-identico ao contrato ja publicado pelo AUR-438/ AUR-439 (ver "Prova de compatibilidade" acima); os exit codes existentes (0, 1, 2) mantem seu significado, e 3 so aparece quando --fail-on e explicitamente dado. --check (AUR-439) continua com seu proprio gate grave-only, agora composto -- nao substituido -- pelo gate de --fail-on. --seguranca, --fail-on, --limite e --modelo no caminho --base nao sao tocados por este card.
  • Migration: not-applicable.
  • Rollback: reverter somente os paths deste card; nenhum estado externo e publicado por ele fora do que o proprio usuario pediu ao rodar o comando.