Pular para conteúdo

AUR-509 — O merge exige uma entrada útil e concisa de changelog

Medido antes (por leitura)

  • internal/changelog só tinha o motor de sugestão (AUR-498/499): classifica commits, calcula o bump e renderiza uma entrada. review.changelog / --changelog publicam essa sugestão; nada verificava se a PR escreveu uma entrada, e nenhum workflow reprovava a falta dela.
  • CHANGELOG.md não tinha seção Unreleased; .aurumcode/config.yml não tinha modo de changelog.
  • analyzer.Repo.Diff (puro Go, ou git quando há binário) devolve um hunk único com contexto completo por arquivo (BuildDiffFile), o que permite reconstruir os dois lados de um arquivo sem tocar em internal/analyzer; arquivo binário ou grande demais vem só em notices.

Decisão

  • internal/changelog/require.go + require_lines.go: Requirement.Verify puro decide sobre os dois lados do arquivo. Padrões (file, section, limites, marcadores de log de agente) ficam em require_defaults.yml embutido, não em Go. Linhas são comparadas como multiconjunto normalizado: reordenar ou mover não é informação nova; a linha nova precisa ter min_words palavras, não ser título e estar em Unreleased ou numa seção de versão (semver pelo parser do próprio motor).
  • internal/config/changelog_check.go: seção changelog_check (nil = off), validada no Parse, governada como batches (política que declara decide sozinha), registrada em governedSections.
  • cmd/aurumcode/cmd_changelog.go + changelog_sides.go: subcomando changelog (registro AUR-572). O modo vem do config.yml da base: se a PR mudou o arquivo, o lado antigo do diff; senão, o checkout. Erro de diff, arquivo em notices, hunk que não seja contexto completo ou config da base inválido → indeterminado, exit 1.
  • .github/workflows/changelog.yml + scripts/ci/changelog-check.sh: roda em pull_request neste repositório e é reutilizável (workflow_call) pelo consumidor. Constrói o binário do checkout da ferramenta (job.workflow_repository@job.workflow_sha) e passa o checkout da PR (head, fetch-depth: 0) como --repo: o verificador nunca vem do código da PR no consumidor. Job de nome estável Changelog obrigatório, sem paths e sem if: (job pulado seria verde); git instalado no alpine (o leitor puro Go não lê packs).
  • O check nunca chama modelo; o texto da entrada é contado, nunca ecoado nem obedecido. A sugestão (review.changelog) fica intacta e separada.

Fora dos paths do card (necessário ao Outcome)

  • .aurumcode/config.yml: changelog_check.mode: required ("este repositório usa esse modo"). Vale a partir do merge, porque o modo é lido da base.
  • CHANGELOG.md: seção ## Unreleased com a entrada deste card.
  • docs/configuration.md (seção nova + linha em "Opções públicas"), docs/index.md (link, regra do AUR-560), mkdocs.yml (nav de docs/changelog.md; o build é --strict), docs/architecture.md (linha do pacote), scripts/ci/changelog-check.sh (semgrep proíbe sh -c em workflow), cmd/aurumcode/aur572_test.go (lista de comandos).

Varredura de documentação desatualizada

grep -i changelog em docs/, README.md, demo/tutoriais e docs/tutorials: nenhuma frase dizia que changelog não bloqueia; só a linha de review.changelog em "Opções públicas" foi esclarecida como sugestão. O tutorial de changelog fica com o AUR-501 (o índice diz "em breve").

Como cada cenário é provado

  • AC-001: TestAUR509AC001RequiredModeRefusesUselessChanges (ausente, ilegível, só espaços, indentação, reordenação, só remoção, só título, palavra solta, fora da seção → reprova; entrada válida e arquivo novo → passa).
  • AC-002: TestAUR509AC002EntryIsConciseAndUserFacing (logs de agente, linha longa, entrada longa reprovam; consolidação de release com resumo passa; release que só move linhas reprova). Exemplos em docs/changelog.md.
  • AC-003: TestAUR509AC003CheckFailsClosed (nome estável, diff com erro, arquivo em notices, config da base inválido → exit 1; sem --base → 2) e TestAUR509AC003PullRequestCannotSwitchItOff; TestAUR509ChangelogCheckSection (parse, modo inválido, path fora do repo, política decide).
  • AC-004: TestAUR509AC004SuggestionStaysSeparate e TestAUR509AC004EntryTextIsData.
  • MUT-001: tests/acceptance/AUR-509.sh MUT-001 troca o retorno de entrada ausente por aprovação em require.go; AC-001 e AC-003 ficam vermelhos.
  • MUT-002: troca o erro de diff por sucesso em cmd_changelog.go; AC-003 fica vermelho.

Limites

  • O teste local não afirma que o merge remoto já bloqueia: isso depende da proteção da main exigir o contexto Changelog obrigatório.
  • O config.yml não alterado pela PR é lido do checkout: localmente, um arquivo sujo na árvore de trabalho vale como base.
  • Neste repositório o workflow roda do merge ref da PR: uma PR pode editar o próprio changelog.yml (inerente a pull_request); a revisão é a guarda.
  • Marcadores de log de agente padrão são só assinaturas inequívocas (--- PASS, /pass, Co-Authored-By, bloco de código...); "exit code" e "tool call" ficaram de fora porque entradas legítimas do produto os usam.
  • Revisão estática do coordenador (2026-10-07): --politica implementado (ValidatePolicyOutsideReviewedTree + LoadCentralPolicy + ApplyCentralPolicy, provado por TestAUR509AC003CentralPolicyDecides); o workflow ganhou policy_repository/policy_ref; nas PRs do próprio AurumCode o verificador vem da base da PR, não do merge.