smith-ai-lab/smith-check

smith check, smith fmt e smith lint: verificação de projeto antes de commit, formatação com .clang-format, análise com clang-tidy e .clang-tidy, e em arquivos .smith. Carregue antes de commitar, quando uma verificação falhar, ou em 'código deve ser formatado com clang-format' e resultados do clang-tidy.

O que é smith-check?

Esta skill integra ferramentas LLVM (clang-format, clang-tidy, clangd) diretamente no comando `smith`, garantindo formatação e linting consistentes em todas as máquinas. Para um projeto, `smith fmt` formata automaticamente arquivos C, C++, Objective-C e `.smith` rastreados pelo git, respeitando as regras de `.clang-format` e `.clang-format-ignore`. `smith lint` executa clang-tidy com cache incremental, analisando apenas fontes modificados, e suporta verificação de arquivos `.smith` com regras específicas de nomenclatura. `smith check` executa uma sequência completa de formatação, lint, testes e prova (análise de contratos), informando cada etapa. A skill também oferece suporte a configurações padrão embutidas, cache inteligente e opções para CI, sendo ideal para desenvolvedores que usam smith como gerenciador de projetos.

Funciona com✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/smith-ai-lab/smith/tree/HEAD/.agents/skills/smith-check

Installed? Explore more Programação e Desenvolvimento skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

smith check, fmt, lint e lsp

smith fmt, smith lint e smith lsp são clang-format, clang-tidy e clangd, vinculados ao smith a partir do mesmo LLVM do compilador, para que toda máquina formate e analise da mesma forma.

No projeto: sem argumentos

Os verbos significam a mesma coisa em todos os projetos e leem o que seu build.c declara; um projeto não escreve tarefa para eles.

  • smith fmt reescreve todo arquivo C, C++, Objective-C e .smith que o git vê (rastreados, e não rastreados mas não ignorados; .c .h .m .mm .cpp .cc .cxx .hpp .hh .smith .metal) para .clang-format (um arquivo .metal é formatado como C++, a linguagem que clang-format dá a uma extensão que ele não conhece). smith fmt --dry-run (ou -n, com --Werror ou -i) e smith lint --quiet são também as formas do projeto: apenas opções, sem nomes de arquivos, então nunca esperam pela entrada padrão; qualquer outra opção, ou um nome de arquivo, os transforma nas ferramentas (smith fmt --assume-filename=x.c lê a entrada padrão). Um arquivo nomeado em .clang-format-ignore (clang-format o lê por si só: um parser.c gerado, uma fixture) é deixado de lado. Fora de um repositório git, informa que é necessário nomear os arquivos (smith fmt -i <arquivos>).
  • smith lint constrói o que os compiladores leem (cabeçalhos gerados), então executa clang-tidy com .clang-tidy nos fontes do próprio projeto entre as compilações da build (smith_object, e smith_compile_command para fontes que a build nunca compila), lado a lado. Não inclui saídas de .smith/, build/ ou pacotes. Cada fonte .smith é analisado como smith lint x.smith -- <flags> faz: os da própria build com seu comando de compilação, e cada outro arquivo .smith que o git vê com o comando de compilação mais próximo, exceto o que .clang-format-ignore nomeia (a única lista de arquivos que não são fontes comuns: entradas de teste, fixtures intencionalmente erradas, arquivos gerados e copiados; smith fmt também a lê, então não há uma segunda lista). Um resultado reprova o lint; sua última linha diz linted N files (smith check: lint ok: N files), e um projeto com fontes .smith que não analisa nenhum reprova. Um .clang-tidy em uma pasta (como InheritParentConfig: true com outras verificações) se aplica ali.
  • smith lint é incremental: o resultado do clang-tidy para um arquivo é armazenado em cache em ~/.cache/smith/lint e reproduzido enquanto o arquivo, o que ele inclui (para um arquivo .smith, também os cabeçalhos gerados dos módulos que importa), seu .clang-tidy e o smith permanecerem inalterados, então a última linha lê smith lint: linted 180 files (3 run, 177 cached, 1.2 s) e uma árvore inalterada não executa clang-tidy em nenhum arquivo. SMITH_LINT_CACHE=0 desliga o cache, SMITH_LINT_CACHE=why informa por que um arquivo foi executado, smith cache clean lint o esvazia. Um arquivo cujo clang-tidy falha é nomeado nas últimas linhas (smith lint: c.c: exited with status 1, ou was killed by signal 9, que não imprime nada próprio) e no final de sua própria saída.
  • smith lint --changed[=<ref>] analisa apenas os arquivos alterados desde a merge-base com <ref> (padrão: o upstream do branch, senão o branch de origin/HEAD ou origin/main, nunca um main local; nenhum deles é um erro nomeando --changed=<ref>; a linha impressa nomeia a base; edições e arquivos não rastreados contam) e os arquivos que os incluem ou importam; um .clang-tidy, arquivo de build, shim/ ou patches/ alterado seleciona todo arquivo, e nada afetado informa isso e é bem-sucedido. Também constrói apenas o que esses arquivos esperam. smith lint simples analisa tudo (CI). Um arquivo que espera por um pacote que a rede não fornece (o parser tree-sitter em um sandbox na nuvem) é pulado por nome (smith lint: skipped runtime/tree_sitter_data.c: the tree-sitter parser it embeds cannot be fetched (<url>)) e o restante é analisado; CI (CI ou SMITH_PRIORITY=ci) reprova em vez disso. smith lint FILE em um projeto ainda não construído (sem compile_commands.json) para e informa para executar smith build smith_needs uma vez, em vez de relatar os cabeçalhos gerados ausentes como erros.
  • smith docs verifica knowledge/ e as skills (smith-docs).
  • smith check executa fmt (dry run do clang-format), docs, lint, test e prove, nessa ordem, e não para em uma falha: cada parte imprime uma linha, smith check: <part> ok: <detail> (<n> s wall, <n> s cpu) ou FAILED (status N) com um trecho limitado da falha e o caminho do log completo (.smith/log/<part>.log; a saída de uma parte bem-sucedida também está lá; smith check -v imprime tudo conforme acontece), então smith check: promises: N (o que o smith confia, de uma build padrão que ele faz se necessário), e a última linha é smith check: ok ou smith check: failed: <parts>; o status de saída é 1 quando algum falha. A linha de prove informa a cobertura, smith check: prove ok (4 of 23 funções): ... (funções com um contrato próprio, do projeto; 0 of N funções quando não há nada a provar, o que é um sucesso; nada falha por baixa cobertura). Cada linha de parte termina com seu tempo wall e CPU ((91.2 s wall, 480.1 s cpu): CPU é usuário mais sistema, da parte e dos processos que esperou). Não aceita argumentos além de opções -D e -v. Em um host que não é macOS, executa os testes com --skip-macos e informa isso (the macOS-only tests do not run on this host). smith test termina com uma tabela das tarefas da build (passos .smith/task/<name>, como os próprios test-<name> do smith), do mais lento ao mais rápido: segundos wall, CPU e sistema e o número de processos smith que cada um iniciou (SMITH_START_LOG, que o smith anexa conforme main começa; uma tarefa que limpa o ambiente não é contada); os oito mais lentos, toda tarefa com smith check -v ou SMITH_ACCOUNT=all, nenhum com SMITH_ACCOUNT=no. As tarefas são executadas através de smith --smith-account <file> <name> <command...>, que escreve a linha.
  • Arquivos .smith na nova sintaxe não são do clang-format (#1890, #1886, #2040): smith fmt envia um arquivo .smith para o próprio formatador do smith (front::format) a menos que esteja na sintaxe atual (uma linha começa com uma forma que apenas a sintaxe atual ou C tem, o parser atual a lê sem erro, ou seu primeiro erro na nova sintaxe tem uma correção, como um comentário //) ou tenha um erro de parse e nenhuma linha que apenas a nova sintaxe tem (fn, let, pub, #): um estilo e nenhum .clang-format para ele (qualquer indentação consistente sai com 4 espaços, uma instrução por linha, comentários # mantidos). Um arquivo de nova sintaxe com erro de parse é relatado como path:line:column: message, deixado byte por byte como estava (com --dry-run também) e faz smith fmt sair com código 1: nunca é enviado ao clang-format, que o danificaria. É idempotente, respeita .clang-format-ignore, e --dry-run / -n nomeia os arquivos que mudariam (path: would be formatted) sem escrever. Um arquivo .smith na sintaxe atual (e todo .c) permanece com clang-format até a transição (#1631) remover esse fallback. Testado por tests/fmt_smith_test.smith.
  • smith fmt FILE recusa um arquivo cuja extensão não seja uma dessas (um .sh, um .md), com um erro que nomeia o arquivo e não escreve nada, pois clang-format o leria como C e o corromperia; --assume-filename=x.c informa o que é.
  • Antes de commitar: smith fmt, depois smith check.
  • Uma tarefa própria (uma verificação personalizada, um gerador) é smith_task no build.c e é executada com smith build <task>; nenhuma tarefa ou alias pode ser nomeado fmt, lint, docs, prove, check, run ou test. smith build check e os outros nomes de verbos são recusados: use o verbo.

Em arquivos: com argumentos

smith lint DIR (uma pasta entre os argumentos) analisa os fontes C, C++, Objective-C e .smith abaixo dela que o git vê e que .clang-format-ignore não nomeia, como o lint do projeto (sem cabeçalhos, que são lidos através de seus fontes); smith lint front -- <flags> e smith lint front/ main.c se misturam com arquivos. Uma pasta sem tal fonte é um erro.

O analisador do clang-tidy (clang-analyzer-*) lê smith_requires, smith_ensures, smith_invariant e smith_assert de <smith/contract.h> como suposições (target::static_analyzer), então um índice limitado por um contrato não é relatado por clang-analyzer-security.ArrayBound.

O .clang-tidy padrão do smith desliga duas verificações do analisador que eram ruído (em game, learner e smith: 546 de 616 resultados): clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling (todo memcpy) e clang-analyzer-optin.performance.Padding. Reative uma no .clang-tidy do próprio projeto (smith lint --dump-config > .clang-tidy escreve o arquivo efetivo) excluindo sua linha -clang-analyzer-....

smith lint --fix FILE.smith... (sem --) aplica as correções que o próprio front-end do smith carrega em seus erros de parse (uma forma antiga ou estilo C com sua grafia smith: as edições de uma correção são aplicadas juntas ou nenhuma, uma correção sobreposta é pulada, e um arquivo é parseado novamente até que nada se aplique, no máximo 16 passos) e imprime path: N fixes applied; uma segunda execução imprime 0 fixes applied. Lê apenas arquivos .smith e precisa do smith completo. Com -- <flags> é o --fix do clang-tidy, acima. Nenhum erro de parse ainda carrega uma correção: as formas antigas recebem suas correções tíquete por tíquete (#1428).

smith lint FILE adiciona --extra-arg=-I para build/<os>/front-project/.smith/include quando essa pasta existe (módulos front importam uns aos outros através dela), e em um host que não é macOS imprime uma linha: CI analisa em um Mac, onde u64 é unsigned long long e usize é unsigned long, então (U64)(i + 1) com um usize é um resultado bugprone-misplaced-widening-cast apenas lá; corrija tal cast escrevendo (U64)i + 1.

Com argumentos, eles são as ferramentas: smith fmt main.c reescreve o arquivo no lugar (clang-format o imprimiria; smith adiciona -i quando você nomeia arquivos e nenhuma opção escolhe outro modo: -n, --dry-run, --lines, --assume-filename mantêm o significado do clang-format, e smith fmt --assume-filename=x.c < x.c imprime o resultado), smith fmt --dry-run --Werror main.c, smith fmt --dry-run --Werror main.c, smith lint --quiet main.c -- <flags>, smith lsp --check=main.c. Um .clang-format e .clang-tidy do projeto se aplicam. Um smith stage0 executa as ferramentas do Homebrew, ou $SMITH_CLANG_FORMAT, $SMITH_CLANG_TIDY, $SMITH_CLANGD.

Padrões do smith, onde um projeto não tem arquivo (issue #43). Um projeto sem .clang-format (ou _clang-format) e sem .clang-tidy, procurados a partir da pasta de cada arquivo e acima como clang-format e clang-tidy fazem, é formatado e analisado com os próprios padrões do smith, embutidos no smith (os arquivos que smith new escreve hoje); não há nada a escrever. Um arquivo no projeto substitui o do smith por completo, nunca mesclado, e um --style (ou --fallback-style), --config ou --config-file explícito vence. Com entrada padrão, --assume-filename nomeia onde procurar. Nomear arquivos com e sem um arquivo de projeto em um único comando funciona (smith executa o segundo tipo como outro processo). smith fmt --dump-config > .clang-format e smith lint --dump-config > .clang-tidy imprimem o efetivo (o do projeto, senão o do smith), então um projeto assume os padrões ao despejá-los e edita o que deseja; os padrões mudam raramente e intencionalmente, então um projeto que os queira fixos os despeja. smith escreve sua cópia para $XDG_DATA_HOME/smith/defaults/ (senão ~/.local/share/...). smith cc nunca é afetado: permanece um passagem pura.

Arquivos .smith

smith fmt x.smith (e -i, --dry-run, entrada padrão com --assume-filename=x.smith) formata um arquivo .smith como C, com seus caminhos ::, linhas module a::b; e import a::b as x; e import <sys/wait.h>; mantidas intactas; smith fmt sem argumentos formata também os arquivos .smith do projeto (o git os vê). import e module dentro de uma função são nomes, como em C. Precisa de um smith cujo clang-format tenha o patch .smith (um stage0 executa o do Homebrew, que lê .smith como C++ e, portanto, lê mal nomes C que são palavras-chave C++, como throw). clangd formata arquivos .smith da mesma forma.

smith lint x.smith -- <flags> (clang-tidy, com o .clang-tidy do projeto) analisa um arquivo .smith como smith cc o lê (-x c, e -std=gnu2y a menos que você nomeie um padrão; o comando próprio de um banco de dados de compilação é usado como está) e relata conforme a fonte está escrita: resultados, notas e correções nas linhas e colunas do texto .smith, com os nomes como escritos (area e Box no módulo, box::area onde é importado, nunca geometry_box_area). readability-identifier-naming julga o nome escrito de nomes de escopo de arquivo de um módulo, então as regras do modelo (funções e variáveis snake_case, tipos PascalCase) se aplicam a area e Box, e --fix reescreve o token na fonte; os tipos de tamanho fixo (U32, I32), as cópias de protótipos do lowering e os cabeçalhos que smith build escreve nunca são relatados. Um resultado sobre uma exportação é relatado no arquivo do módulo, não em cada importador, e uma correção lá não renomeia os importadores. Outras verificações mostram os nomes escritos em suas mensagens, mas uma verificação que compara o nome em si (uma verificação de comprimento ou nome reservado, por exemplo) ainda lê o nome rebaixado. Precisa de um smith cujo clang tenha o token hook (smith cc --smith-which x.smith informa token-hook yes); um stage0 executa o clang-tidy do Homebrew, que não consegue ler .smith.

Também nesta família: smith-check-lints.

Habilidades Relacionadas