Pular para conteúdo

AUR-494 — Novas rodadas preservam findings válidos sem repetir comentários

Medido antes (leitura do código em stream/B)

  • Já existia: o histórico do PR (reviews, comentários inline e gerais) é lido a cada --pr e entra no prompt como contexto não confiável (pr_history.go); a identidade canônica de achado (render.FindingIdentityFor + render.FindingFingerprint, AUR-521) lê o código da linha no diff, nunca o texto do modelo; o cache de revisão (AUR-513) e o de veredito mudam de chave com prompt, configuração, perfis e contexto; o achado fora do diff vira comentário geral (AUR-545); o evento formal segue o gate (AUR-600).
  • Faltava: cada rodada republicava todo comentário de achado (inline e geral); nada ligava um comentário anterior ao achado atual. A identidade canônica inclui o número da linha, então mover o mesmo código mudaria a impressão. O parecer não registrava o que deixou de ser reportado.
  • docs/review-quality.md e README.md diziam "sem garantia de deduplicação" e "não atualiza comentários anteriores"; corrigidos.

Decisão

  • internal/review/rounds (novo): Marker escreve o marcador oculto <!-- aurumcode:finding <sha256> <regra> -->; Published lê os marcadores do histórico (respostas em thread não contam); PlanRound casa as impressões da rodada com as anteriores por contagem (duas ocorrências do mesmo defeito precisam de dois comentários) e lista as anteriores não reencontradas.
  • cmd/aurumcode/pr_rounds.go: roundFingerprint reaproveita a identidade canônica do AUR-521 com a linha zerada quando há código na linha (mover o trecho mantém a identidade; outra regra na mesma linha é outro achado). planRound usa as entradas do histórico já lidas para o prompt (pullRequestHistoryContext passa a devolvê-las; nenhuma requisição a mais). Sem histórico legível, tudo é comentado.
  • review_pr_publish.go: revisão formal e modo de comentários pulam o comentário de achado já comentado e anexam o marcador aos novos; o corpo ganha "Rodadas anteriores" com a contagem do não repetido e a lista do não reencontrado (review.round_* no catálogo internal/i18n).
  • O achado pulado continua em result.Issues: parecer, gate, evento formal e status não mudam; marcador forjado só evita um comentário repetido, nunca desliga regra. Resposta de pessoa só entra no prompt.

Desvio de paths do card

Os textos novos ficam em internal/i18n/catalog.yml (regra do catálogo: toda interface por idioma vem dele) e o README.md foi corrigido pela regra de documentação desatualizada; os demais arquivos estão em cmd/aurumcode, internal/review e docs/review-quality.md.

Fora do escopo

Dispensar uma revisão REQUEST_CHANGES de rodada anterior exige um método novo em internal/git/githubclient (fora dos paths): o evento e os status da rodada atual já deixam de bloquear; a dispensa fica documentada como limitação. O achado fora do diff (AUR-545) não leva marcador.

Como cada cenário é provado (tests/acceptance/AUR-494.sh)

Os testes de cmd/aurumcode/aur494_test.go rodam rodadas reais de --pr contra um GitHub falso que guarda a conversa (o que uma rodada publica é o que a próxima lê).

  • AC-001: TestAUR494AC001SameDiffTwiceNoDuplicateComment (segunda rodada: zero comentários, mesmo evento, contagem no corpo) e os testes de internal/review/rounds.
  • AC-002: TestAUR494AC002MovedCodeKeepsIdentityNewDefectStays.
  • AC-003: TestAUR494AC003FixRemovesBlockAndTextDisablesNothing (resposta "falso positivo" chega ao prompt e o evento continua REQUEST_CHANGES; depois da correção o evento deixa de ser REQUEST_CHANGES e o corpo registra a resolução) e TestPublishedIgnoresReplies.
  • AC-004: TestAUR494AC004NewContextFindsNewDefectWithoutRepeating.
  • MUT-001: roundPlan.posts passa a devolver sempre true; compila e o AC-001 fica vermelho com AUR-494 duplicate comment.

Correções da revisão estática

  • Um achado agrupado por review.presentation.collapse (AUR-454) entrava em "não se repetem" embora continuasse reportado. PlanRound recebe também os achados agrupados (stillReported): nunca comentados, nunca resolvidos. Prova: TestPlanRoundCondensedIsNeverResolved.
  • Execução inconclusiva (falha do modelo ou gate inconclusivo) não lista nada como resolvido (conclusiveForRounds). Prova: TestAUR494InconclusiveRunNamesNothingResolved.
  • O marcador era aceito de qualquer autor: o autor do PR podia forjá-lo, calar o comentário de um achado e injetar um "corrigido". Agora só conta marcador de comentário cujo autor é AURUMCODE_PUBLISHER_LOGIN; o workflow reutilizável o define como github-actions[bot] (autor do github.token). Sem esse login, nenhum marcador é lido e tudo é comentado de novo (falha fechada). O cliente GitHub não tem leitura do usuário autenticado e GET /user não responde a token de instalação, por isso o login vem do ambiente da borda. Risco residual: outro workflow do mesmo repositório que publique com github.token escreve como o mesmo login. Prova: TestAUR494ForgedMarkerFromAnotherAuthorIsIgnored.
  • O texto "já comentado em rodada anterior" do stdout vem do catálogo (review.round_repeated_line).