Arquitetura do Sistema de Tooling
Este documento descreve o runner de lint, test e typecheck da implementacao Rust.
Visao geral
O sistema de tooling fica em src/tooling/ e usa um strategy por linguagem.
src/tooling/
├── python.rs
├── rust.rs
├── runner.rs
├── types.rs
└── typescript.rs
Componentes principais
ToolingRunner
Responsavel por:
- detectar o tipo de projeto
- descobrir ferramentas disponiveis
- filtrar arquivos por check
- executar checks e fixes
- formatar a saida dos resultados
Arquivo: src/tooling/runner.rs
LanguageStrategy
Cada linguagem implementa:
name()detection_files()lint_extensions()typecheck_extensions()test_patterns()default_tools()discover_tools()filter_files_for_check()
ToolCommand
Representa uma ferramenta detectada:
namecommandcheck_typeblockingpass_filesextensionsfix_commandauto_fix
Arquivo: src/tooling/types.rs
ToolResult
Representa o resultado de execucao:
successoutputblockingskippedskip_reason
Ordem de deteccao
Hoje a prioridade de deteccao e:
- TypeScript
- Rust
- Python
Se project_type estiver definido no .seshat/config.yaml, ele vence a autodeteccao.
Fluxo de execucao
ToolingRunner::new(path)
-> ProjectConfig::load(path)
-> detect_strategy(path, config)
run_checks(check_type, files)
-> discover_tools()
-> get_tools_for_check(check_type)
-> run_tool(tool, files)
Dentro de run_tool:
- filtra os arquivos relevantes para aquele check
- pula o tool se nao houver arquivo relevante
- injeta argumentos derivados dos arquivos quando
pass_files=true - usa
fix_commandseauto_fix=true - executa o processo com timeout de 300s
Comportamento por linguagem
Rust
Defaults atuais:
lint:rustfmttypecheck:cargo clippy --all-targets --all-features -- -D warningstest:cargo test
Regras especiais do Rust:
lintusaskip_children=truepara evitar cascata em modulos filhoslintdetecta aeditiondoCargo.tomltypechecke convertido para-p <crate>com base no arquivo afetadotestso roda para integration tests emtests/*.rs- se houver exatamente um integration test staged e exatamente uma funcao de teste nova no diff staged,
testrecebe tambem o nome da funcao - quando mais de um arquivo do mesmo crate entra no check, o pacote e deduplicado
Python
Defaults por deteccao:
ruffouflake8para lintmypypara typecheckpytestpara test
Regras especiais do Python:
pytestrecebe arquivos de teste relevantes por default- arquivos em
tests/outest/, arquivostest_*.py,*_test.py,tests.pyeconftest.pycontam como testes - se houver exatamente um arquivo de teste staged e exatamente uma funcao
test_*nova no diff staged,pytestrecebe o nodeid do teste - metodos de classe sao convertidos para
arquivo.py::Classe::test_nome
TypeScript
Defaults por deteccao:
eslintoubiometsc --noEmitjestouvitest
Regras especiais do TypeScript:
jestevitestrecebem arquivos.test.*e.spec.*por default- se o
package.jsontiver scripttest, o runner chamanpm run test -- <args> - se houver exatamente um arquivo de teste staged e exatamente um
test(...)ouit(...)novo no diff staged, o runner passaarquivo -t nome
Checks por arquivo vs checks por projeto
O runner combina as duas abordagens:
lintnormalmente usa arquivos explicitostestetypecheckpodem transformar arquivos em outros argumentos
Exemplos no Rust:
tests/e2e_cli.rs->--test=e2e_clitests/e2e_cli.rscom um unico#[test] fn novo_testestaged ->--test=e2e_cli novo_testecrates/core/src/lib.rs->-p core
Exemplos em outras linguagens:
tests/test_app.pycom um unicodef test_criadostaged ->tests/test_app.py::test_criadotests/test_app.pycom um unico metodo novo emclass TestApp->tests/test_app.py::TestApp::test_criadosrc/app.test.tscom um unicotest("cria app", ...)staged ->src/app.test.ts -t "cria app"
Overrides
Existem dois niveis de override:
checks.<tipo>
Exemplo:
checks:
lint:
blocking: true
auto_fix: false
commands.<tool ou tipo>
Exemplo:
commands:
rustfmt:
auto_fix: true
typecheck:
command: ["cargo", "clippy", "--workspace", "--", "-D", "warnings"]
commands.* e aplicado sobre o tool detectado.
Auto-fix
Quando auto_fix=true e existe fix_command:
- o runner executa o fix em vez do comando de check
- o resultado aparece como sucesso ou falha do check
- no fluxo de commit, os arquivos explicitos podem ser re-stageados depois
No Rust atual:
rustfmttemfix_commandembutidochecks.lint.auto_fix: falsedesliga esse comportamento
Como adicionar uma nova linguagem
- Criar um novo strategy em
src/tooling/<linguagem>.rs - Implementar
LanguageStrategy - Registrar o strategy em
detect_strategy - Adicionar testes unitarios no modulo de
runner - Adicionar e2e quando houver comportamento especial de filtros ou argumentos