vet: veredito sobre código gerado por IA

O codafort vet dá um veredito sobre o que mudou desde HEAD ou desde a base do PR: o que bloqueia, o que é consultivo e o que não rodou.

Ele avalia só o delta, em cinco eixos. O que está provado vai para blocking e reprova; o resto vai para advisory. O veredito diz quais eixos não rodaram, e eixo pulado nunca conta como limpo.

Uso

codafort vet                              # o delta vs HEAD (mudanças não-commitadas)
codafort vet --all                        # o projeto inteiro
codafort vet --json                       # o veredito completo, coda-vet/1 (agentes/CI)
codafort vet --base origin/main           # num PR: o delta é vs a BASE, não vs HEAD
codafort vet --ingest tsc.out             # correlaciona o que o CI já rodou (tsc/junit-xml/lcov)
codafort vet --evidence-out vet.json      # grava coda-evidence/1 (modality: vet) para a declaração contra-assinada

Exit codes: 0 passa · 1 veredito bloqueante · 2 erro de execução. Com o 2, uma falha de execução nunca é lida como bloqueio.

Os eixos

EixoPerguntaBloqueia?
V0-security-deltaHá finding de segurança novo na mudança? (a mesma análise do scan, só no diff)confirmado sim; suspeito é consultivo
V1-ingested-diagnosticsO tsc/junit/lcov que o CI já rodou tem error em linha nova?error sim; warning aconselha
V2-vacuous-testsTeste que passa sem testar (assert True, sem asserção, mock que devolve o esperado)?consultivo
V3-public-contractSímbolo público removido/renomeado (contract_breaks)?sim
V4-blast-radiusEscopo: arquivos, linhas, arquivos críticos tocados, wide?consultivo; alimenta prioridade
healthComplexidade ciclomática/cognitiva das funções tocadasnunca

V1 só roda com --ingest; V3/V4 precisam de um delta. Quando não rodam, aparecem em axes.skipped, e não em ran.

A codafort não executa tsc, pytest nem outra ferramenta: ela lê o artefato que o CI já produziu e o cruza com o diff.

A forma do veredito (coda-vet/1)

{
  "schema": "coda-vet/1",
  "blocked": true,
  "axes": { "ran": ["V0-security-delta", "V2-vacuous-tests", "V3-public-contract", "V4-blast-radius"],
            "skipped": ["V1-ingested-diagnostics"] },
  "blocking": [ { "id": "SF-1", "severity": "Critical", "tier": "confirmed", "rule": "TAINT-COMMAND-INJECTION",
                  "cwe": [78], "file": "./app.py", "line": 7, "is_new": true,
                  "taint": { "source": "os.environ", "sink": "os.system" } } ],
  "advisory": [],
  "ingested": [],
  "contract_breaks": [ { "file": "./app.py", "symbol": "antiga_api", "kind": "function" } ],
  "scope": { "files_changed": 1, "lines_added": 4, "critical_files": [], "wide": false },
  "diff_only": true
}

Contrato publicado em /schemas; um veredito real capturado em /schemas/fixtures/coda-vet.json.

No CI (GitHub Action)

- uses: actions/checkout@v4
  with: { fetch-depth: 0 }          # a BASE precisa existir localmente
- uses: codafort/gate-action@v1
  with:
    source: '.'
    vet: 'true'                     # default
    vet-base: 'origin/main'         # vazio = base do PR (github.base_ref)
    vet-ingest: 'tsc.out'           # opcional: artefato já produzido pelo CI
    vet-enforce: 'true'             # um veredito BLOQUEANTE reprova o job

Num checkout raso, o step tenta git fetch da base. Se ela não resolver, o vet é pulado com ::warning (report-only) ou reprova (vet-enforce: true); ele nunca passa em silêncio sem ter rodado. Detalhes em CI e gate.

Do veredito à declaração contra-assinada

--evidence-out vet.json grava a contribuição coda-evidence/1 com modality: "vet": blocking, advisory, scope, axes_ran, axes_skipped, verdict_digest. Anexada com codafort attest create --evidence vet.json, ela entra no ledger que a codafort contra-assina. Ver A cadeia de evidência e Declaração contra-assinada (o artefato coda-attestation/1).