Pular para conteúdo

AUR-592: Aurum para quem programa com agente de IA

Medido antes (base 959b71df)

  • O parecer do Aurum só chegava na PR (CI) ou por aurumcode review --base no terminal. Nenhum agente de código (Claude Code, Codex, Cursor) tinha como perguntar ao gate antes do commit; não havia servidor MCP, skill de agente nem hook de pre-commit.
  • runReviewWith construía a sessão --base inline, e a resolução das regras de skill (catálogo da política e do repositório, regras dinâmicas) vivia dentro de baseReview.selectProvider: não havia como listar as regras que valem para um caminho sem rodar uma revisão.
  • A revisão local cobre base..HEAD (commits), não o índice nem a árvore de trabalho (computeDiff em cmd/aurumcode/local_diff.go).

O que mudou

  • internal/mcpserver (novo): o adaptador MCP por stdio.
  • jsonrpc.go: o subconjunto JSON-RPC 2.0 que o MCP exige, isolado num arquivo (uma mensagem por linha, notificações sem resposta, lote recusado, linha limitada a 1 MiB). Decisão: sem o SDK oficial Go (github.com/modelcontextprotocol/go-sdk), porque ele não está no cache offline de módulos e uma dependência nova exigiria go get com rede e repin da imagem selada; o subconjunto (initialize, tools/list, tools/call, ping) é pequeno e tem testes de protocolo.
  • tools.go: as quatro ferramentas (aurum_review, aurum_gate, aurum_rules, aurum_explain), cada uma com JSON Schema fechado (additionalProperties: false) e anotação readOnlyHint.
  • args.go: decodificação estrita (DisallowUnknownFields) e validação antes de executar: a ref não começa por - nem contém ..; caminhos são relativos ao repositório; finding_id tem 12 hex.
  • gateway.go: a porta Gateway (Review, Rules). O servidor não decide.
  • decision.go: a decisão é lida da sessão (código de saída e motivo de inconclusivo do gate.Result); pass só com saída 0, revisão conclusiva e mudança não vazia. Mudança vazia entre base e HEAD é inconclusive (empty_change): mais estrito que a CLI, de propósito, porque o agente que pergunta antes de commitar não pode ler "nada revisado" como pass.
  • redact.go: o único ponto de redação; toda resposta (inclusive o stderr da sessão, que no gateway é um buffer e não o writer redigido da CLI) passa pelo filtro do processo e pelo filtro final da sessão.
  • server.go: o laço stdio, o limite de tempo por chamada (--tempo; estourou é inconclusive, time_limit) e uma revisão por vez.
  • cmd/aurumcode:
  • review_base.go: newBaseReview, o único construtor da sessão --base, usado pela CLI e pelo servidor.
  • skill_catalog.go: resolveSkillRules, a única resolução de catálogo e regras de skill, usada pela sessão e por aurum_rules.
  • cmd_mcp.go: o subcomando mcp (flags --tempo, --limite), no registro único de comandos.
  • mcp_gateway.go / mcp_rules.go: o gateway monta a linha review --base <ref> --seguranca --exigir-qualidade (o agente só recebe respostas mais estritas que um review --base puro), roda session.Run e lê gateRes, result, securityApart e notReviewed.
  • .agents/skills/aurum-review/SKILL.md (formato Agent Skills) e .agents/skills/aurum-review/hooks/pre-commit (hook opcional que revisa o índice numa worktree temporária).
  • docs/agentes.md (nav), docs/index.md, docs/architecture.md (módulo e seção do adaptador), docs/configuration.md (seção CLI aurumcode mcp, que o --help do comando cita), tutorial demo/tutoriais/agente e docs/tutorials/agente.md, capturas.

Prova

Aceite (tests/acceptance/AUR-592.sh, go-shared)

Seletor O que prova Última linha
AC-001 cliente MCP em stdio lista as 4 ferramentas; aurum_gate/aurum_review dão o mesmo código de saída, o mesmo relatório e os mesmos achados bloqueantes (vs. auditoria) que review --base no mesmo diff (skill do repo + segredo); conformidade do protocolo AUR-592/AC-001/pass
AC-002 sob AURUMCODE_POLICY, aurum_rules lista skills policy e repository; nenhum schema declara propriedade além de base/paths/finding_id AUR-592/AC-002/pass
AC-003 nenhuma resposta contém o canário do diff; argumento extra/inválido recusado (-32602) sem a sessão rodar; provedor ausente, provedor que falha e mudança vazia são inconclusive AUR-592/AC-003/pass
AC-004 skill com front matter name/description que manda chamar aurum_gate; página com claude mcp add, .mcp.json, Codex, Cursor na nav; tutorial com os casos e run.sh --check AUR-592/AC-004/pass
MUT-001 o gateway com caminho de gate próprio (só resolve/evidence/model e decide por contagem de achados error) compila e reprova TestMCPGateIsTheReviewSessionGate (o relatório diverge do review --base) AUR-592/MUT-001/rejected
MUT-002 sem o ponto de redação (toolResult(answer)), TestEveryAnswerIsRedacted reprova: o canário aparece em achados, relatório, stderr e linhas do gate AUR-592/MUT-002/rejected

Escopo da MUT-002: ela reprova no servidor, com um gateway que entrega texto cru. De ponta a ponta a sessão já redige os campos do modelo e o relatório; o ponto de redação do servidor é a segunda barreira e a única sobre o stderr da sessão, que no gateway é um buffer.

O relatório de aurum_review é o stdout da sessão depois do filtro de redação inteiro; por isso AC-001 compara com Redact(stdout da CLI). Quando o relatório cita security/hardcoded-secret: <título>, o filtro reescreve o título (a CLI evita isso redigindo campo a campo); os achados estruturados mantêm rule_id intacto.

Tutorial e regressão (execução real)

  • Imagem do produto construída uma vez desta árvore (AURUMCODE_TUT_IMAGE=aurum-tutoriais:aur592 AURUMCODE_TUT_REBUILD=1), demo/tutoriais/agente/run.sh all e os outros 18 tutoriais com -P4: todos rc=0; run.sh --check dos 19: CHECK OK (sbom-dependency-track terminou com o caso down).
  • bash scripts/docs/capturas.sh: capturas: 239 imagens no manifesto; bash scripts/docs/build.sh: 0 avisos.
  • go vet ./... limpo; go test -p 1 ./... sem falha.
  • Aceites (go-shared): AUR-592, 576, 580, 593, 572, 561, 562, 563, 564 e 588 all: pass. AUR-443 falha com as mesmas 5 linhas --- FAIL em main (959b71df) e neste ramo: defeito anterior a este card.
  • Selado: oci-run --profile go-unit-offline-v1 --card AUR-592: "exit_code":0. No selado só cmd/aurumcode é materializado (paths do card), então a identidade da árvore de out/.imagem não pode bater; o AC-004 então exige os 4 casos ok contra expected/ e a divergência ser só de árvore. A árvore é conferida onde cmd/ está inteiro (AUR-561..564, CI e o --check local).

Decisões e pendências

  • O hook ficou em .agents/skills/aurum-review/hooks/pre-commit, e não em scripts/hooks/, porque scripts/ não está nos paths do card. docs/configuration.md foi tocado fora dos paths (a seção que o --help do comando mcp cita).
  • A revisão por MCP vê commits (base..HEAD); o índice é coberto pelo hook. Revisar a árvore de trabalho sem commit ficaria para um card próprio (uma fonte de diff nova na sessão, não no servidor).
  • Defeito existente, fora deste card: com AURUMCODE_CACHE_DIR definido, uma segunda execução de review --base --seguranca sobre o mesmo conteúdo reaplica o achado de segurança em Review.Issues pelo reaproveitamento de veredito e o imprime duas vezes (o teste de AC-001 usa cache novo por execução para comparar sessões equivalentes).