Pular para conteúdo

AUR-587: guia de extensão no site e tutorial executável de exemplo

Medido antes (base 9c685fde)

  • O site publicava docs/architecture.md (em inglês) com uma seção "Extension points" curta; não havia guia de extensão nem tutorial que mostrasse como estender o produto.
  • O registro de engines (internal/scanner/engines) importava só gitleaks e semgrep; o Dockerfile compilava go build sem tags.
  • demo/tutoriais/_lib/tutorial.sh construía uma única imagem por árvore, sem build args; out/.imagem registrava tree, dockerfile e image.

O que mudou

  • docs/extensao.md ("Estendendo o Aurum", pt-BR, na navegação de mkdocs.yml logo após Arquitetura): os quatro pontos de extensão com o contrato real (engine de scanner: scanner.Scanner, Request, Report, Finding.ToIssue, Engine, Register, Executor, FailureReason, quality_gates.scanners, required; ferramenta de deliberação: deliberation.Tool, Result, Limits, LimitError, Transcript, o manifesto de internal/review/tools; skill: arquivo listado, SKILL.md, catálogo em camadas; fonte de contexto: config.ContextProvider, ProviderTimeout, MaxProviderContributionBytes, o lugar do MCP, AUR-469), um exemplo mínimo por ponto e "O que NÃO é ponto de extensão" (plugin dinâmico, texto do modelo alterando o gate, MCP como autoridade, engine fora do registro).
  • internal/scanner/engines/exemplo: engine de exemplo sem binário externo; reporta cada linha da árvore revisada (sem .git) que contém a marca EXEMPLO-ACHADO (regra exemplo:marca, severidade error, origem e categoria exemplo, Report.Version exemplo 1; arquivo acima de 1 MiB é pulado; árvore ilegível é erro, logo inconclusivo). O pacote não se registra: internal/scanner/engines/exemplo_registro.go (//go:build aurum_exemplo) é o único que o importa e chama scanner.Register.
  • Dockerfile: ARG GO_TAGS="" no estágio builder, usado em go build -tags "$GO_TAGS". Sem o argumento o binário é o de antes.
  • demo/tutoriais/_lib/tutorial.sh: TUT_BUILD_ARGS (declarado no run.sh antes do source; AURUMCODE_TUT_BUILD_ARGS sobrescreve) vira --build-arg; com build args a tag ganha o sufixo -<12 hex dos args> (também sob AURUMCODE_TUT_IMAGE), então a imagem padrão dos outros tutoriais nunca é sobrescrita; out/.imagem ganha build_args= e o --check reprova build args diferentes (linha ausente vale vazio); tut_image_padrao e TUT_RUN_IMAGE deixam um caso rodar a imagem padrão.
  • Tutorial docs/tutorials/extensao.md + demo/tutoriais/extensao (TUT_BUILD_ARGS="GO_TAGS=aurum_exemplo"), casos engine-no-gate, skill-no-prompt, ferramenta-pedida e falha-binario-padrao; registrado em docs/tutorials/README.md, demo/tutoriais/README.md e docs/index.md (seção "Estendendo o Aurum", que liga guia e tutorial). Nav: o hook scripts/docs/hooks.py injeta tutorials/extensao.md na seção Tutoriais (sem mudança no hook).
  • docs/architecture.md: só edições aditivas (o AUR-583 edita o mesmo arquivo em paralelo): uma linha na tabela de pacotes para internal/scanner/engines/exemplo e o parágrafo "Veja o guia de extensão" no fim de "Extension points".
  • Testes: internal/scanner/engines/exemplo/exemplo_test.go (achados determinísticos, árvore limpa completa, raiz ilegível inconclusiva, sem opções); internal/scanner/engines/registro_padrao_test.go (!aurum_exemplo: não registrada, config.Parse recusa engine: exemplo); registro_exemplo_test.go (aurum_exemplo: registrada com origem exemplo, Parse aceita); guia_test.go: cada pkg.Nome e pkg.Tipo.Membro citado no guia (pacotes scanner, exemplo, deliberation, tools, skills, config, llm) existe no go/ast do pacote (nomes de topo, métodos por receptor, campos de struct, métodos de interface), um conjunto mínimo do contrato é citado e há ao menos 25 citações distintas.

Fora do escopo / pendente

  • AC-004 parcial: docs/architecture.md continua em inglês. O briefing adiou a tradução para depois do AUR-583 (que edita a tabela de camadas e cmd/aurumcode/structure_test.go/architecture_doc_test.go), para evitar conflito. A tabela continua lida por architecture_doc_test.go, que passa. A tradução fica como pendência deste card ou de um card seguinte.
  • Plugin dinâmico, MCP real (AUR-469), mudança de contratos existentes, engine de exemplo no binário padrão: non-goals.

Como cada AC/MUT foi provado

Aceite: tests/acceptance/AUR-587.sh (seletores all, AC-001..AC-004, MUT-001, MUT-002). O selado não tem docker: a engine é provada por go list -deps/go test com e sem a tag, e o tutorial pelo out/ gravado e --check.

  • AC-001: guia no nav (- Estendendo o Aurum: extensao.md), as cinco seções, e TestExtensionGuideCitesTheRealContract verde. Site: bash scripts/docs/build.sh (que roda mkdocs build --strict) com 0 warnings; no site/search/search_index.json construído, "engine", "ferramenta", "skill" e "ContextProvider" têm hits em extensao/.
  • AC-002: go list -deps ./cmd/aurumcode contém o pacote de exemplo 0 vezes sem tag e 1 vez com -tags aurum_exemplo; TestDefaultBuildRefusesExampleEngine (sem tag) e TestTaggedBuildRegistersExampleEngine (com tag) verdes; run.sh --check do tutorial CHECK OK; o out/ tem a linha do gate com origem exemplo, auditoria blocking_findings: ... origin=exemplo, sarif result: ... origin=exemplo, unknown engine "exemplo" no binário padrão e build_args=GO_TAGS=aurum_exemplo em out/.imagem.
  • AC-003: prompt: Uma funcao faz uma coisa so. MARCA-SKILL-EXEMPLO e o eco da fixture no out/skill-no-prompt.log; auditoria chamada: rodada=1 ferramenta=scanner_exemplo status=executed resultado=1 achado(s) no out/ferramenta-pedida.log.
  • AC-004 (parcial, ver acima): TestAUR558ArchitectureDocCitesEveryInternalPackage verde; architecture.md e index.md ligam o guia; index.md liga o tutorial.
  • MUT-001: sem exemplo_registro.go o pacote some do binário com tag, o teste com tag falha com example engine not registered, e um out/ sem a origem exemplo faz o --check reprovar (DIVERGENCIA caso=engine-no-gate).
  • MUT-002: acrescentar scanner.Scanner.Scan ao guia reprova o teste do guia (cites names the packages do not declare: scanner.Scanner.Scan).

Execução real do tutorial

Imagens construídas desta árvore (AURUMCODE_TUT_IMAGE=aurum-tutoriais:aur587; a do tutorial é aurum-tutoriais:aur587-<sufixo dos args>):

  • extensao/engine-no-gate: exit 3, (severidade error, limiar error, origem exemplo, secao repo).
  • extensao/skill-no-prompt: exit 0, o prompt traz a skill e a fixture ecoa.
  • extensao/ferramenta-pedida: exit 3, rodada 1 scanner_exemplo({}) executed: 1 achado(s).
  • extensao/falha-binario-padrao: exit 1, quality_gates.scanners[exemplo].engine: unknown engine "exemplo" (registered: gitleaks, semgrep).

Os 18 tutoriais foram reexecutados em paralelo com a imagem desta árvore (o Dockerfile e internal/ mudaram, então todo out/.imagem mudou) e o out/ de cada um foi commitado; run.sh --check passa em todos.

Config do tutorial fora de .aurumcode/

TestAUR575ExistingConfigsStayValid (internal/config) valida, com o binário padrão, todo config.yml sob um diretório .aurumcode em demo/, tests/ e docs/. A configuração com engine: exemplo só vale no binário com a tag, por isso o tutorial a guarda como demo/tutoriais/extensao/config-engine.yml e config-ferramenta.yml; o run.sh (repo_engine) a copia para o .aurumcode/config.yml do repositório descartável e apaga esse repositório ao fim do caso (apaga_repo). Sem mudar o teste nem internal/config.

Regressão (container go-shared, em série)

  • go vet ./... && go vet -tags aurum_exemplo ./internal/scanner/... && go test -p 1 ./...: verde.
  • AUR-587.sh all → AUR-587/all/pass; AUR-577.sh all → AUR-577/all/pass; AUR-580.sh all → AUR-580/all/pass; AUR-561..564 all verdes; AUR-572.sh all e AUR-586.sh all verdes.
  • AUR-560.sh all falhava com index-missing-capability também no main 74121dba (seções de configuration.md sem link no índice: gate.triage, deliberação e "Quais arquivos saem da revisão como documentação"). docs/index.md passou a ligar as três; AUR-560.sh all → AUR-560/all/ok.
  • bash scripts/docs/build.sh: 0 warnings.
  • Selado: oci-run --profile go-unit-offline-v1 --card AUR-587 → exit_code 0.