← Todos os projetos

mido

CLI que roda seis checagens e bloqueia a mudança até tudo passar. Feito pro meu fluxo com agentes de IA.

  • 10,4klinhas de Rust
  • 349testes
  • 97,8%cobertura
  • 100%mutantes mortos (102)
Papel
Autor e mantenedor
Stack
Rust · CLI · MCP · cargo-mutants · Nix
Links
GitHub

Contexto

“Se você quer passar por aqui, é melhor estar com espada e escudo.” — Mido, guardando a entrada da Floresta Kokiri

mido é uma ferramenta de linha de comando que roda uma escada de verificação de seis portões — sintaxe, tamanho, análise, testes, cobertura e mutação — contra um workspace inteiro, na ordem de custo, e bloqueia a passagem até que cada portão passe. Se o nome vem do personagem que não deixa ninguém entrar sem provas, o comportamento é o mesmo.

Ele nasceu do problema de verificar código escrito com agentes de IA: quando um LLM escreve a mudança, algo precisa provar que a mudança se sustenta. O primeiro diff que ele mediu foi o frontend do Maya.

O problema

Ferramentas de qualidade normalmente avisam; não decidem. Para um fluxo em que um agente escreve e outro lê o resultado, isso não basta:

  • um pipeline verde não prova quase nada: testes que executam código sem assegurar comportamento passam do mesmo jeito;
  • “não rodou” costuma ser tratado como “passou” — a categoria mais perigosa que existe;
  • e um veredito precisa ser consumível por uma máquina: sem festa visual, sem interação, sem interpretação.

O que faltava não era um linter a mais; era uma escada com contrato: uma ordem só, um vocabulário só, e exit codes para um agente ramificar.

Como foi construído

Um crate único de Rust, biblioteca + binário, organizado em camadas:

  • gate — a folha do sistema: o vocabulário dos seis gates (nomes, ordem, dicas de correção) vive aqui e só aqui, consumido pela CLI, pelo schema de configuração e pelos relatórios;
  • gates — um módulo por portão, com dispatch exaustivo;
  • seam de linguagem — todo o comportamento específico de stack (comandos padrão, parsers de saída, detecção de alvos) fica atrás de um módulo por linguagem; hoje, Rust;
  • configuração estrita — o .mido.toml tem schema versionado e chave desconhecida é erro: a escada se recusa a adivinhar o que um typo queria dizer;
  • relatórios — painéis e markdown; e um servidor MCP que expõe a escada como ferramentas (list_targets, run_ladder) direto para agentes que falam o protocolo.

O veredito é carimbado na revisão exata que ele mediu — commit mais hash do estado sujo —, então um resultado verde de antes da última edição não pode ser reaproveitado nela.

Decisões e trade-offs

  • Opinativa de propósito. Sem plugins, sem gates customizados: a escada é a opinião. Isso limita extensibilidade e em troca garante que “verde” signifique sempre a mesma coisa.
  • Comandos são arrays de argumentos, nunca linhas de shell. O que o .mido.toml declara é exatamente o que roda — um agente editando a configuração não consegue contrabandear um pipeline para dentro de um gate.
  • Pulado nunca é aprovado. Um gate desligado reporta SKIPPED; um gate sem ferramenta reporta INCOMPLETE. Nenhum dos dois vira veredito verde. “Não rodou” não é evidência.
  • Ordem por custo. O portão barato roda primeiro; o mutante, que é caro, roda por último — falha rápida, verificação profunda só quando vale a pena.
  • Saída determinística para máquinas. Quando a saída é redirecionada, cor e linha de status somem: o que um agente captura é um log estável e diffável.

Qualidade e verificação

mido se verifica com a própria escada. No último ciclo completo documentado:

  • 349 testes, entre unitários e de integração — os de integração exercitam o binário compilado e o servidor MCP por stdio;
  • 97,8% de cobertura;
  • 102 mutantes mortos, 100% — nenhum mutante sobrevivente no sweep fresco. (O piso configurado é 70%; o resultado é o que os testes de fato matam, não o que o piso permite.)
  • portões de tamanho e análise limpos.
╭─ mido ──────────────────────────────────────────────╮
│ target   workspace (./)                             │
│ revision febf29d1                                   │
│ dirty    bddc06f7                                   │
│ measured 14 files (14 rust)                         │
╰─────────────────────────────────────────────────────╯
  Cargo.toml
  src/style.rs

  [1/1] ✓ syntax  clean
      format: 0 file(s) with diffs
      lint: 0 diagnostic(s)
      typecheck: 0 diagnostic(s)

╭─ verdict ──╮
│ SHIP-READY │
╰────────────╯

O processo também encontrou bugs na própria contabilidade de mutação — resultados cacheados sendo lidos como se fossem de uma execução nova, vereditos rápidos e vazios. A correção foi fazer cada execução dona do próprio diretório de saída e pontuar só o que de fato executou. Uma ferramenta de verificação vale exatamente o quanto ela é honesta.

Resultados

A escada tem um contrato de veredito claro: SHIP-READY (exit 0), BLOCKED (exit 1) e INCOMPLETE (exit 2), com relatório de falha que funciona como prompt para o próximo agente: posição na escada, contrato do gate, evidência e dicas de correção escritas como instruções. Hoje ela guarda um produto comercial em desenvolvimento — e é a base sobre a qual eu aceito mudanças feitas por IA no meu próprio código.

O que aprendi

Verificação só vale se for honesta sobre o que não rodou. E a decisão de design mais frutífera foi assumir que o leitor é uma máquina: exit codes, JSON e MCP mudaram a ferramenta inteira — do formato da saída à forma como os erros são escritos.