AUR-591: o Aurum revisa o Aurum por PR, com configuração mínima e skills de convenção
Medido antes (base b29ca936)
.aurumcode/config.ymlsó declaravareview.language: pt-BReignore: tests/**: semgate, sem scanners, sem deliberação, sem skills..aurumcode/skills/não existia..github/workflows/code-review.ymlchama./.github/workflows/review.yml(check obrigatório demain:review / Review pull request). Os secretsLLM_API_KEY/LLM_BASE_URLexistem no repositório; a última execução (2026-10-02, PR do dependabot, sem secrets) falhou no passo "Check provider configuration" sem publicaraurumcode/policy-gatecom o motivo.- Os cards eram integrados por merge local e push direto em
main. - Medido com o binário da base (container
go-shared): uma skill em.aurumcode/skills/<nome>/SKILL.mdchega ao prompt, mas um achado que a cita (tamanho#...ouSKILL#...) é descartado (1 citing an unknown rule_id). Regras citáveis vêm só dereview.context.skills, com id<nome-do-arquivo>#<slug>; listado, oSKILL.mdgeraSKILL#<slug>e o achado reprova o gate (rc 3). - Medido na imagem do produto construída deste worktree
(
aurumcode-review:aur591, a mesma receita doreview.yml), primeiro num repositório de um arquivo e depois sobre a árvore real (clone do worktree, fixture de modelo sem achados,review --base): govetligado:lint_unavailableem toda revisão (a imagem não trazgo) → inconclusivo → bloqueio.semgrep(árvore inteira,p/security-audit+p/owasp-top-ten):sast_invalid_output, porque o relatório traz 13 erros de parse nívelwarn(scripts bash,action.yml, locks YAML), e 9 achadosERRORem arquivos que a PR não tocou (Dockerfiles,demo/bad-code.go,secrets: inheritdocode-review.yml). Ligado, bloquearia toda PR.gitleaks(intervalo da PR): sem achados nem inconclusivo.- Num intervalo que toca
docs/assets/capturas/capturas.json: achadosanalysis/hardcoded-secret(as capturas reproduzem os canários dos tutoriais) →docs/assets/capturas/**entrou noignore. - Cobertura parcial: um arquivo oculto por
ignore(ex.:tests/acceptance/AUR-591.sh) ou um binário (PNG das capturas, mesmo sob caminho ignorado) conta como cobertura parcial (partial_coverage), que cominconclusive: blockreprova. O gate imprime só o motivo de maior rank: na primeira medição ele estava escondido atrás dosast_*.
O que mudou
.aurumcode/config.yml(20 linhas úteis, comentado, depois do merge do AUR-593):review.language,ignorecomtests/**edocs/assets/capturas/**,gate: {fail_on: [error], inconclusive: block},quality_gates.scannerscomgitleaks(required: true),semgrepegovet(fail_on: warning), edeliberationligada commax_rounds: 3,max_cost_tokens: 60000,per_tool_timeout_seconds: 120. Nenhuma skill listada emreview.context.skills: as de diretório já são citáveis..aurumcode/skills/<nome>/SKILL.md(formato do AUR-565,pathsentre aspas), uma por convenção, cada regra com id próprio, exemplo de violação e de correção:arquitetura:ARQ-001lógica eminternal/,cmd/só monta (warning).tamanho:TAM-001função ≤150 linhas,TAM-002arquivo ≤400 (error).sem-numero-de-card:CARD-001sem id de card em código/doc de pacote (warning).repo-publico:PUB-001sem empresa/domínio interno/repo privado,PUB-002sem segredo (error).sem-bool-exportado:BOOL-001sem parâmetroboolem função exportada (error).gate-fail-closed:GATE-001erro/ausência/dúvida nunca aprova (error). Ids citáveis<dir>#<slug>:arquitetura#arq-001-logica-fica-em-internal-cmd-so-monta,tamanho#tam-001-funcao-com-no-maximo-150-linhas, etc. Cada skill só entra no prompt quando um arquivo alterado casa com o seupaths. As regras subjetivas (ARQ-001,CARD-001) ficam emwarning(publicam sem reprovar); as objetivas têmseverity: errorcomo piso..github/workflows/code-review.yml: comentário explicando que, numpull_request,job.workflow_shadoreview.ymllocal é o commit de merge da PR (o binário que revisa é o da PR); novo job paraleloprovider(semneeds, porque check pulado conta como aprovado) que, semLLM_API_KEY/LLM_BASE_URL, publicaaurumcode/policy-gate=failurecom o motivo e sai 1; com os secrets, sai 0 sem publicar nada (quem decide o status é o review).review.ymlnão mudou..board/README.md,.board/AGENT_PLAYBOOK.md,CLAUDE.md: integração por PR (card → branch → PR → CI + self review → merge só com tudo verde); push direto emmainsó para commits que tocam apenas.board/.docs/getting-started.md: a seção "Configuração mínima" é a do AUR-593 (conflito do merge resolvido com o texto domain), mais uma linha apontando a configuração do próprio AurumCode.tests/acceptance/AUR-591.sh: seletoresall,AC-003,MUT-001,MUT-002.
Depois do AUR-593 (merge de main em card/AUR-591)
O AUR-593 tirou ignorados e binários da conta de cobertura, limitou Semgrep e
go vet às linhas adicionadas, tornou as skills de diretório citáveis como
<dir>#<slug> e pôs Go na imagem de review. As lacunas registradas acima
(cobertura parcial por ignore, Semgrep na árvore inteira, govet sem go,
skill de diretório não citável) foram medidas antes dele e estão resolvidas;
semgrep e govet voltaram ligados e a listagem em review.context.skills saiu.
Medição do intervalo deste card (review --base origin/main, merge-base
6d722898) na imagem do produto construída do worktree
(aurumcode-review:aur591), com a configuração nova, fixture de modelo sem
achados e, como no review.yml, os módulos baixados antes com
go mod download para o cache montado em /go/pkg/mod:
rc=0
aurumcode review: deliberation: o provedor não chama ferramentas; os scanners opcionais rodam sem consulta ao modelo
- 1 arquivo(s) ignorados (configuração `ignore` do repositório ou binários): ficam fora da conta de cobertura ...
- tests/acceptance/AUR-591.sh
No issues found.
Sem inconclusivo de cobertura nem de scanner. Sem o cache de módulos (sem o
passo de prefetch), o govet sai lint_execution_error e bloqueia: é o
fail-closed esperado, e o review.yml faz o prefetch.
Pendências
- Binário de
maincomo referência (Outcome item 4): não feito. Um segundo chamador publicaria um segundoaurumcode/policy-gateno mesmo contexto, e o último a terminar venceria. - O teto
max_cost_tokens: 60000não foi conferido contra o uso real de tokens (o provedor de fixture não chama ferramentas); conferir na auditoria da PR do AC-001. - A PR deste card é revisada com a configuração e as skills de
main(base); o novocode-review.ymlvale já (workflow vem do merge ref). Por isso a AC-002 exige uma segunda PR, aberta depois do merge.
Prova (binário do worktree)
O perfil selado não tem git; o aceite escreve o repositório de teste como
objetos soltos com um auxiliar Go só de biblioteca padrão (mkrepo, gerado
pelo próprio script) e o produto lê os objetos sem a CLI do git. Executado
em go-shared e num container --network=none sem git
(aurum-bootstrap-go-bash:1.27.1-2026-10-06, imagem candidata do AUR-590):
$ bash tests/acceptance/AUR-591.sh all
useful lines: 20
real rc=1 # config real: Parse estrito ok; gitleaks/semgrep ausentes no perfil -> inconclusivo, bloqueia
typo rc=1 # fail_on -> fial_on: "field fial_on not found", nenhum prompt
skills rc=3 # skills selecionadas por paths no prompt; achado cita a skill e reprova
longa.go:4: [warning] Funcao Longa tem 160 linhas. (rule tamanho#tam-001-funcao-com-no-maximo-150-linhas: TAM-001 Funcao com no maximo 150 linhas)
mutation rc=0 # MUT-001: sem tamanho/SKILL.md o mesmo achado some
aurumcode review: 1 finding(s) discarded: 1 citing an unknown rule_id (tamanho#tam-001-funcao-com-no-maximo-150-linhas)
api --method POST repos/example/repo/statuses/0123...4567 -f state=failure -f context=aurumcode/policy-gate -f description=self review nao executado: secrets LLM_API_KEY e LLM_BASE_URL ausentes
mutated guard exit=0 caught # MUT-002: guarda com `exit 0` no lugar de `exit 1` é pega
AUR-591/all/pass
- AC-003:
AUR-591.sh AC-003(≤30 linhas úteis, chaves declaradas, Parse estrito real e com erro de digitação, skills no prompt, gate cita a skill). Sobre a árvore real, na imagem do produto: ver "Depois do AUR-593" (rc 0). - MUT-001: o fixture do modelo é fixo; o que muda é só a presença do arquivo da skill. Sem ele o achado é descartado como regra desconhecida e o check fica verde (rc 0): o achado depende da skill, não de regra fixa.
oci-run --profile go-unit-offline-v1 --card AUR-591: inconclusivo nesta máquina (pinned profile image is not present locally: aurum-bootstrap-go-bash@sha256:3aa0ce99...) na primeira rodada; repetido depois do merge do AUR-590 com a imagem fixadab678437d...:exit_code: 0, stdoutAUR-591/all/pass.- MUT-002: a guarda é extraída de
code-review.ymlentre os marcadoresprovider-guard-begin/ende executada com umghfalso que registra os argumentos.
Roteiro do coordenador (AC-001, AC-002, AC-004)
Pré-requisito: secrets LLM_API_KEY, LLM_BASE_URL e variável LLM_MODEL
presentes (gh secret list; gh variable list).
AC-001 e AC-004 (PR deste card):
cd /home/paape/repos/AurumCode
git push -u origin card/AUR-591
gh pr create --base main --head card/AUR-591 \
--title "AUR-591: o Aurum revisa o Aurum por PR" \
--body "Card AUR-591. Spec: docs/specs/AUR-591.md"
N=$(gh pr view card/AUR-591 --json number --jq .number)
gh pr checks "$N" --watch
HEAD=$(gh pr view "$N" --json headRefOid --jq .headRefOid)
gh api "repos/Mpaape/AurumCode/commits/$HEAD/statuses" \
--jq '.[] | select(.context=="aurumcode/policy-gate") | [.state,.description] | @tsv'
gh pr view "$N" --json reviews,comments --jq '[.reviews[].state, (.comments|length)]'
# o binário revisor é o da PR: o SHA do "Checkout AurumCode" é o merge commit
gh api "repos/Mpaape/AurumCode/pulls/$N" --jq .merge_commit_sha
RUN=$(gh run list --workflow code-review.yml --branch card/AUR-591 -L1 --json databaseId --jq '.[0].databaseId')
gh run view "$RUN" --log | grep -A3 'Checkout AurumCode' | grep -E 'ref|sha' | sed -n '1,5p'
# merge só com tudo verde; --merge preserva os SHAs do Delivery record
gh pr merge "$N" --merge --delete-branch
git fetch origin && git merge-base --is-ancestor <sha-do-delivery> origin/main && echo ancestor
Registre na spec/card: URL da PR, estado do review, linha do
aurumcode/policy-gate, e o merge_commit_sha comparado ao SHA do checkout.
AC-002 (depois do merge, com a configuração nova já na base):
cd /home/paape/repos/AurumCode
git fetch origin && git switch -c teste/convencao-funcao-longa origin/main
mkdir -p internal/sondaconvencao
{ printf 'package sondaconvencao\n\n// Longa soma uma unidade por passo.\nfunc Longa() int {\n\ttotal := 0\n'
for i in $(seq 155); do printf '\ttotal++\n'; done
printf '\treturn total\n}\n'; } > internal/sondaconvencao/longa.go
git add internal/sondaconvencao/longa.go
git commit -m "teste: funcao de 160 linhas para provar a convencao de tamanho"
git push -u origin teste/convencao-funcao-longa
gh pr create --base main --head teste/convencao-funcao-longa \
--title "teste de convencao (nao integrar)" --body "Prova da AC-002 do AUR-591; sera fechada sem merge."
M=$(gh pr view teste/convencao-funcao-longa --json number --jq .number)
gh pr checks "$M" --watch # esperado: review / Review pull request = fail
gh pr view "$M" --json reviews --jq '.reviews[].body' | grep -o 'tamanho#tam-001-funcao-com-no-maximo-150-linhas' | sed -n '1p'
HEAD=$(gh pr view "$M" --json headRefOid --jq .headRefOid)
gh api "repos/Mpaape/AurumCode/commits/$HEAD/statuses" \
--jq '.[] | select(.context=="aurumcode/policy-gate") | [.state,.description] | @tsv'
gh pr close "$M" --delete-branch
git switch main && git branch -D teste/convencao-funcao-longa
Se o modelo não citar a skill, a AC-002 não está provada (não reabra com
outro texto até passar: registre o parecer recebido). MUT-001 real, opcional:
na mesma branch de teste, um commit que apaga
.aurumcode/skills/tamanho/SKILL.md não muda o parecer (a configuração vem
da base); por isso o MUT-001 é provado localmente no aceite.
Correções vindas da PR #87
- CI
Build and test in OCIvermelho (TestAUR548*, TestAUR567GateLine…, TestAUR572Conclusive…, TestAUR575SAST…: exit 1, "LLM quality review did not run"): reproduzido na imagemgolang:1.27.1-alpine3.24do CI só combash; combash gito mesmogo testpassa. Causa: desde o AUR-593 os scanners mapeiam as linhas adicionadas comgit diff, e sem git o scan é inconclusivo. Os comandos do job passaram parascripts/ci/build-test.sh(POSIX sh, instalabash gitquando faltam) escripts/ci/race.sh(imagem bookworm, que já traz git), chamados porsh/bash scripts/ci/...semsh -clongo. O script completo passou na imagem do CI. - Auditoria e SARIF não gravados (
audit_write_failed/sarif_write_failed: permission denied): reproduzido localmente. O container roda como root, mas o arquivo montado ficava no/tmpdo container (sticky e gravável por todos) e era de outro uid (o do runner); comfs.protected_regularoopen(O_CREAT)falha com EACCES mesmo para root.review.ymlagora monta o diretório${RUNNER_TEMP}/aurumcode-outem/aurumcode-out(fora de/tmp), grava auditoria, SARIF e saída do changelog ali, devolve os arquivos ao uid do runner com umchownno fim e mantém o código de saída do review. Na PR, a autorrevisão passou a gravar os dois artefatos. - "go mod download failed": não houve falha. A linha aparece no log só
porque o GitHub imprime o script do passo antes de executá-lo; nenhum
##[warning]foi emitido, e o govet concluiu (a revisão chegou a um achado, não alint_*inconclusivo). - Achado SCR-001 em
ci.yml:52(sh -ccom sequência longa como command injection): a string não interpola nenhuma entrada externa (nem${{ github.event.* }}, nem variável do PR); é texto fixo do workflow. Como insumo de realimentação da regra: umsh -ccom literal fixo, sem expressão do GitHub nem variável controlada pelo PR, não é injeção. O refactor foi feito mesmo assim (scripts versionados). A linha antigash -c 'npm install ... node tests/docs/mkdocs.test.cjs'do job de documentação não foi alterada por esta PR e ficou: o aceite do AUR-588 exige o textonode tests/docs/mkdocs.test.cjsdentro doci.yml. scripts/ci/está fora dospathsdo card; criado por pedido do coordenador.- Pré-existente, não corrigido:
tests/acceptance/AUR-496.shAC-003 já falha emmain(runs-pr-code) por causa do passo de prefetch de módulos do AUR-593.