Ir para o conteúdo

Regras do contrato

contract.md é prosa para o modelo mais um bloco cercado que a CLI avalia:

```rules
dependencies pyproject.toml django psycopg "pytest*"
forbid-pattern "shop/domain/**" "from shop\.infrastructure"   # DEC-002 layering
forbid-path "web/src/**/*.js"                                 # TypeScript only
require-command "python -m pytest -q"
```

Uma regra por linha, aspas ao estilo shell, # inicia um comentário que é exibido como a razão nos relatórios.

Regras

forbid-path <glob>

Nenhum arquivo pode corresponder ao glob. check olha os arquivos que a entrega alterou; audit, todo arquivo rastreado e não rastreado fora de .atipspec/.

forbid-pattern <glob> <regex>

Nenhum arquivo que corresponda ao glob pode conter uma linha que corresponda à expressão regular (sintaxe Python). A primeira linha correspondente é reportada com seu número. Use isso para camadas ("from shop\.infrastructure|^from django" no domínio), para bibliotecas banidas, ou para padrões que suas convenções proíbem.

dependencies <manifest> <name-or-glob>...

O manifesto só pode declarar as dependências listadas. Os nomes são comparados em minúsculas; globs como "@types/*" ou "pytest*" são permitidos. Em check a regra roda quando o manifesto está entre os arquivos que a entrega alterou; em audit ela sempre roda. Manifestos suportados:

Arquivo Lido de
pyproject.toml project.dependencies, project.optional-dependencies, dependency-groups, dependências e grupos do Poetry
requirements*.txt um requisito por linha, linhas -r/-e são ignoradas
package.json dependencies, devDependencies, peerDependencies, optionalDependencies
Cargo.toml dependencies, dev-dependencies, build-dependencies
go.mod linhas e blocos require

require-command <command>

O plano de toda entrega deve incluir o comando, literal a menos de espaços em branco e das aspas do shell, em pelo menos um Verify: de uma tarefa, sozinho ou seguido de mais argumentos: com require-command "python -m pytest" conta a linha python -m pytest -q --junitxml .atipspec/tmp/junit.xml, que escreve um Report:. Não conta uma linha que segue o comando com um operador de controle (|, ||, &&, ;, &), um redirecionamento (>, <, 2>&1) ou uma substituição de comandos ($(...), crases): python -m pytest || true e python -m pytest | tail -1 passam quer os testes passem, quer não. No Windows, onde verify executa a linha com cmd.exe, que não lê como aspas nem as simples nem as barras invertidas, também não conta uma linha com &, |, <, >, ^, % ou aspas duplas em qualquer lugar depois do comando, mesmo entre aspas que o sh respeitaria. Os argumentos não são julgados: um que restringe a execução, como -k smoke ou um único arquivo de testes, conta do mesmo jeito, porque distingui-lo de --junitxml depende da ferramenta; o humano vê cada linha Verify: na proposta. É assim que os portões de qualidade do contrato se tornam evidência em cada entrega.

Globs

** atravessa diretórios, * e ? não. Os padrões são ancorados ao caminho inteiro relativo à raiz do projeto: src/**/*.js corresponde a src/c.js e src/a/b/c.js; src/*.js corresponde só ao primeiro.

Onde as regras se aplicam

atipspec check <slug> atipspec audit
Arquivos alterados desde a base da entrega, mais não rastreados todos os rastreados e não rastreados, fora de .atipspec/
dependencies quando o manifesto mudou sempre
require-command o plano da entrega não aplicável
Resultado erros no portão da entrega erros, saída 1

Alterando o contrato

Uma entrega cujo diff toca .atipspec/contract.md fica vermelha a menos que um novo arquivo sob .atipspec/decisions/ faça parte do mesmo diff e a aceitação registrada do contrato o inclua. Crie-o com atipspec decision <slug> --title ... --affects contract:<section>; o assistente apresenta atipspec proposal contract e, depois da sua aprovação explícita, a registra com atipspec accept contract --code <code>, que define o status da decisão. Um status definido como accepted à mão não conta. Com uma política de confiança externa, a decisão precisa, em vez disso, de sua aprovação assinada pela engenharia.