Tutorial: estendendo o Aurum na prática
Objetivo
Ao final você terá visto, rodando, três dos pontos de extensão do
guia de extensão: uma engine de scanner de exemplo
compilada no produto por tag de build, cujo achado reprova o gate e chega à
auditoria e ao SARIF com origem exemplo; uma skill de exemplo entrando
no prompt que o modelo recebe; e uma ferramenta de deliberação pedida pelo
modelo, com a chamada registrada no transcript da auditoria. A falha mostra o
outro lado: o binário padrão não contém a engine de exemplo e recusa
engine: exemplo ao ler a configuração.
Cada comando e cada saída vêm de uma execução real, registrada em
demo/tutoriais/extensao/out/ e conferida por run.sh --check. Os blocos de
configuração são os arquivos de demo/tutoriais/extensao/, byte a byte.
Pré-requisitos
git,docker,bashepython3. Nada mais roda no seu host.- Duas imagens do produto, construídas do
Dockerfileda raiz: a padrão e a de exemplo, com a engine compilada pela tagaurum_exemplo(oDockerfilepassaGO_TAGSaogo build -tags):
docker build -t aurumcode:local /caminho/para/AurumCode
docker build --build-arg GO_TAGS=aurum_exemplo -t aurumcode:exemplo /caminho/para/AurumCode
- Rede não é necessária: a demonstração roda com
--network nonee com o provedor de modelo falso (AURUMCODE_LLM_FIXTURE).
bash demo/tutoriais/extensao/run.sh all # quatro casos; grava out/
bash demo/tutoriais/extensao/run.sh --check # compara out/ com expected/, sem docker
O run.sh declara TUT_BUILD_ARGS="GO_TAGS=aurum_exemplo": a imagem do
tutorial ganha o sufixo dos build args na tag, e out/.imagem registra
build_args=GO_TAGS=aurum_exemplo, então ela nunca se confunde com a imagem
padrão dos outros tutoriais.
A engine de exemplo
A engine (internal/scanner/engines/exemplo) reporta cada linha da árvore
revisada que contém a marca EXEMPLO-ACHADO, sem binário externo. O
repositório liga a engine como qualquer outra, no .aurumcode/config.yml
(o run.sh copia config-engine.yml para lá no repositório descartável;
o arquivo fica fora de .aurumcode/ no tutorial porque só vale no binário
com a tag, e o repositório descartável é apagado ao fim do caso):
quality_gates:
scanners:
- engine: exemplo
gate:
fail_on: [error]
O pull request acrescenta a marca:
def soma(a, b):
# EXEMPLO-ACHADO: marca que a engine de exemplo reporta
return a + b
Caso 1: o achado da engine no gate, na auditoria e no SARIF
bash demo/tutoriais/extensao/run.sh engine-no-gate
$ aurumcode review --base main --auditoria /work/auditoria.json --sarif /work/revisao.sarif
aurumcode review: policy gate: exemplo:marca - linha marcada para o exemplo de engine do guia de extensao (rule exemplo:marca) (severidade error, limiar error, origem exemplo, secao repo)
app.py:2: [error] linha marcada para o exemplo de engine do guia de extensao (rule exemplo:marca)
exit_code=3
RESULTADO: a engine de exemplo achou a marca no diff e o gate reprovou com origem exemplo
auditoria blocking_findings: rule_id=exemplo:marca path=app.py line=2 origin=exemplo
sarif result: exemplo:marca app.py:2 origin=exemplo
A linha do gate diz origem exemplo; a auditoria (blocking_findings) e o
SARIF (properties.origin) carregam a mesma origem tipada, que vem do
registro da engine e nunca do modelo.
Caso 2: a skill de exemplo no prompt
A skill é Markdown, listada em review.context.skills:
review:
language: pt-BR
context:
skills:
- .aurumcode/skills/exemplo.md
# Skill de exemplo
## Funcoes pequenas
severity: warning
Uma funcao faz uma coisa so. MARCA-SKILL-EXEMPLO
O modelo falso ecoa o que viu: quando o prompt contém MARCA-SKILL-EXEMPLO
ele devolve a sugestão "Eco da skill" dizendo isso. O caso também captura o
prompt (AURUMCODE_PROMPT_CAPTURE) e mostra a linha da skill:
bash demo/tutoriais/extensao/run.sh skill-no-prompt
$ aurumcode review --base main
- **Eco da skill** — o prompt recebido trazia a skill de exemplo (MARCA-SKILL-EXEMPLO)
exit_code=0
RESULTADO: a skill chegou ao prompt; sem engine nem gate o exit e 0
prompt: Uma funcao faz uma coisa so. MARCA-SKILL-EXEMPLO
Caso 3: a ferramenta pedida pelo modelo
Com a deliberação ligada, a entrada required: false não roda antes do
modelo: vira a ferramenta scanner_exemplo, oferecida no manifesto do
prompt. O run.sh copia config-ferramenta.yml para o
.aurumcode/config.yml do repositório descartável.
deliberation:
enabled: true
max_rounds: 3
max_cost_tokens: 60000
per_tool_timeout_seconds: 60
quality_gates:
scanners:
- engine: exemplo
required: false
gate:
fail_on: [error]
O modelo falso pede a ferramenta (tool_calls) e responde depois de ver o
resultado:
{"aurumcode_fixture": {
"tool_calls": [
{"tool": "scanner_exemplo"}
],
"cases": [
{"prompt_contains": "exemplo: 1 achado",
"response": {"issues": [], "summary": "A ferramenta pedida devolveu 1 achado da engine de exemplo."}}
],
"default": {"issues": [], "summary": "A ferramenta de exemplo nao foi pedida."}
}}
bash demo/tutoriais/extensao/run.sh ferramenta-pedida
$ aurumcode review --base main --auditoria /work/auditoria.json
aurumcode review: deliberation: oferecidas [scanner_exemplo, codebase_context, read_file, search_text, find_symbol, changed_file_diff]; pedidas [scanner_exemplo]; não pedidas [codebase_context, read_file, search_text, find_symbol, changed_file_diff]; rodadas 2; desfecho answered
aurumcode review: deliberation: rodada 1 scanner_exemplo({}) executed: 1 achado(s)
aurumcode review: gate verdict reuse unavailable (AURUMCODE_CACHE_DIR not set): this run's verdict cannot be shared with another run, and could not reuse one either
aurumcode review: policy gate: exemplo:marca - linha marcada para o exemplo de engine do guia de extensao (rule exemplo:marca) (severidade error, limiar error, origem exemplo, secao repo)
## AurumCode code review
> [!CAUTION]
> **Blocked: 1 problem must be fixed before merge.**
policy gate: failed · 1 file reviewed
app.py:2: [error] linha marcada para o exemplo de engine do guia de extensao (rule exemplo:marca)
exit_code=3
RESULTADO: o modelo pediu scanner_exemplo, o achado contou no gate com origem exemplo
auditoria deliberation: oferecidas=scanner_exemplo,codebase_context,read_file,search_text,find_symbol,changed_file_diff pedidas=scanner_exemplo rodadas=2 desfecho=answered
auditoria chamada: rodada=1 ferramenta=scanner_exemplo status=executed resultado=1 achado(s)
A chamada fica no transcript (deliberation da auditoria) e o achado conta
no gate com origem exemplo, qualquer que seja a resposta do modelo.
Quando falha
O binário padrão (imagem sem build args) não contém a engine de exemplo. A
mesma configuração do caso 1 é recusada ao ler .aurumcode/config.yml,
antes de qualquer revisão: o registro de engines é fechado, e uma engine que
o binário não tem nunca é carregada em tempo de execução.
bash demo/tutoriais/extensao/run.sh falha-binario-padrao
$ aurumcode review --base main
aurumcode review: parsing /work/.aurumcode/config.yml: quality_gates.scanners[exemplo].engine: unknown engine "exemplo" (registered: gitleaks, govet, semgrep)
exit_code=1
RESULTADO: o binario padrao recusa engine: exemplo como engine desconhecida
Próximos passos
- O contrato de cada ponto de extensão: Estendendo o Aurum.
- A deliberação com o Semgrep: Deliberação com ferramentas.
- Skills em camadas e política central: Skills de convenção.
Como fica
Capturas geradas por scripts/docs/capturas.sh a partir das saídas gravadas em demo/tutoriais/extensao/out/: o terminal de cada caso e, quando o caso publica, o comentario do PR e os status checks. O manifesto docs/assets/capturas/capturas.json registra o digest de cada insumo.
engine-no-gate


falha-binario-padrao

ferramenta-pedida


skill-no-prompt

