sentry-test 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. sentry_test-1.0.0/LICENSE +21 -0
  2. sentry_test-1.0.0/PKG-INFO +265 -0
  3. sentry_test-1.0.0/README.md +233 -0
  4. sentry_test-1.0.0/pyproject.toml +21 -0
  5. sentry_test-1.0.0/setup.cfg +4 -0
  6. sentry_test-1.0.0/src/sentry_test.egg-info/PKG-INFO +265 -0
  7. sentry_test-1.0.0/src/sentry_test.egg-info/SOURCES.txt +50 -0
  8. sentry_test-1.0.0/src/sentry_test.egg-info/dependency_links.txt +1 -0
  9. sentry_test-1.0.0/src/sentry_test.egg-info/entry_points.txt +2 -0
  10. sentry_test-1.0.0/src/sentry_test.egg-info/top_level.txt +1 -0
  11. sentry_test-1.0.0/src/sentrytest/__init__.py +3 -0
  12. sentry_test-1.0.0/src/sentrytest/adapters/__init__.py +1 -0
  13. sentry_test-1.0.0/src/sentrytest/adapters/case_specs.py +244 -0
  14. sentry_test-1.0.0/src/sentrytest/adapters/local_tools.py +320 -0
  15. sentry_test-1.0.0/src/sentrytest/adapters/toml_config.py +9 -0
  16. sentry_test-1.0.0/src/sentrytest/application/__init__.py +0 -0
  17. sentry_test-1.0.0/src/sentrytest/application/analyze.py +190 -0
  18. sentry_test-1.0.0/src/sentrytest/application/cases.py +115 -0
  19. sentry_test-1.0.0/src/sentrytest/application/coverage_context.py +13 -0
  20. sentry_test-1.0.0/src/sentrytest/application/dimensions.py +91 -0
  21. sentry_test-1.0.0/src/sentrytest/application/error_paths.py +139 -0
  22. sentry_test-1.0.0/src/sentrytest/application/impact.py +70 -0
  23. sentry_test-1.0.0/src/sentrytest/application/reporting.py +208 -0
  24. sentry_test-1.0.0/src/sentrytest/application/traceability.py +159 -0
  25. sentry_test-1.0.0/src/sentrytest/cli.py +206 -0
  26. sentry_test-1.0.0/src/sentrytest/domain/__init__.py +1 -0
  27. sentry_test-1.0.0/src/sentrytest/domain/catalog.py +78 -0
  28. sentry_test-1.0.0/src/sentrytest/domain/models.py +100 -0
  29. sentry_test-1.0.0/src/sentrytest/domain/rules.py +62 -0
  30. sentry_test-1.0.0/src/sentrytest/init_project.py +89 -0
  31. sentry_test-1.0.0/src/sentrytest/ports/__init__.py +1 -0
  32. sentry_test-1.0.0/src/sentrytest/ports/inputs.py +32 -0
  33. sentry_test-1.0.0/src/sentrytest/skills.py +211 -0
  34. sentry_test-1.0.0/tests/test_analyze.py +302 -0
  35. sentry_test-1.0.0/tests/test_case_specs.py +146 -0
  36. sentry_test-1.0.0/tests/test_cases_application.py +116 -0
  37. sentry_test-1.0.0/tests/test_changed_coverage.py +166 -0
  38. sentry_test-1.0.0/tests/test_cli.py +115 -0
  39. sentry_test-1.0.0/tests/test_contextual_reporting.py +83 -0
  40. sentry_test-1.0.0/tests/test_dimensions.py +86 -0
  41. sentry_test-1.0.0/tests/test_domain_models.py +19 -0
  42. sentry_test-1.0.0/tests/test_error_paths.py +114 -0
  43. sentry_test-1.0.0/tests/test_execution_evidence.py +108 -0
  44. sentry_test-1.0.0/tests/test_git_context.py +144 -0
  45. sentry_test-1.0.0/tests/test_history_cli.py +121 -0
  46. sentry_test-1.0.0/tests/test_impact.py +74 -0
  47. sentry_test-1.0.0/tests/test_init_project.py +70 -0
  48. sentry_test-1.0.0/tests/test_input_adapters.py +6 -0
  49. sentry_test-1.0.0/tests/test_reporting.py +41 -0
  50. sentry_test-1.0.0/tests/test_rules.py +88 -0
  51. sentry_test-1.0.0/tests/test_toml_config.py +43 -0
  52. sentry_test-1.0.0/tests/test_traceability.py +155 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Lucas Nicolau Ferreira
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALING IN THE
21
+ SOFTWARE.
@@ -0,0 +1,265 @@
1
+ Metadata-Version: 2.4
2
+ Name: sentry-test
3
+ Version: 1.0.0
4
+ Summary: Test quality intelligence for change-oriented reviews
5
+ Author: Lucas Nicolau Ferreira
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Lucas Nicolau Ferreira
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALING IN THE
26
+ SOFTWARE.
27
+
28
+ Requires-Python: >=3.11
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ Dynamic: license-file
32
+
33
+ # Sentry
34
+
35
+ CLI de qualidade de teste orientada a mudança. O `sentry` cria a pasta da spec, valida a matriz de casos em markdown, roda a suíte, lê o diff e a cobertura, e emite um veredito auditável — e deixa o fluxo escrito para o agente de IA que for implementar a mudança.
36
+
37
+ Markdown é a fonte da intenção: a CLI parseia e valida `CASES.md` e `PROMPT.md` — ela nunca os escreve. O agente de IA faz a redação; o Sentry garante estrutura, rastreabilidade e veredito.
38
+
39
+ > Não confundir com o [Sentry da getsentry](https://sentry.io) (monitoramento de erros). Este projeto é distribuído como `sentry-test`.
40
+
41
+ ## A divisão de responsabilidade
42
+
43
+ - **O agente de IA declara intenção** — escreve o `CASES.md`: requisito, camada, tipo, prioridade, entrada, resultado esperado.
44
+ - **O Sentry mede a realidade** — decide status, teste associado, evidência e veredito.
45
+
46
+ O agente nunca escreve status. O Sentry nunca chama um modelo. É isso que torna o veredito auditável e reproduzível.
47
+
48
+ ## Instalação
49
+
50
+ ```bash
51
+ pip install sentry-test
52
+ ```
53
+
54
+ Requer Python 3.11+. Confira com `sentry --version` (imprime a versão do pacote).
55
+
56
+ Se faltar `pytest` ou `coverage`, o `init` avisa. Para instalar junto:
57
+
58
+ ```bash
59
+ sentry init --install
60
+ ```
61
+
62
+ ## Setup
63
+
64
+ ```bash
65
+ cd seu-projeto
66
+ sentry init
67
+ ```
68
+
69
+ Cria `.sentry/` (specs, execuções, relatórios e banco), o `sentry.toml`, as entradas do `.gitignore`, e escreve o fluxo em dois lugares:
70
+
71
+ - **Skill `sentry-cases`** em `.claude/skills/sentry-cases/SKILL.md` — carregada automaticamente pelo Claude Code e por agentes que seguem essa convenção.
72
+ - **`AGENT-SENTRY.md`** na raiz do projeto — o mesmo fluxo em markdown puro, sem depender de convenção de nenhuma ferramenta.
73
+
74
+ Para outros agentes (Cursor, Windsurf, Codex, opencode), aponte-os para o `AGENT-SENTRY.md` no arquivo de regras que cada um já usa — por exemplo, uma linha em `.cursor/rules` ou `AGENTS.md`:
75
+
76
+ ```markdown
77
+ Para escrever ou revisar casos de teste, siga AGENT-SENTRY.md.
78
+ ```
79
+
80
+ `init` é idempotente: não apaga histórico, não sobrescreve configuração existente, não duplica estruturas.
81
+
82
+ ## O fluxo
83
+
84
+ 1. `sentry new "cadastro de cliente"` — cria `.sentry/specs/cadastro-de-cliente/` com `PROMPT.md` (pedido preservado) e `CASES.md` em branco
85
+ 2. **`sentry-cases`** — seu agente pergunta o que estiver ambíguo e preenche o `CASES.md` seguindo o template
86
+ 3. `sentry check cadastro-de-cliente` — estrutura válida? classes de equivalência do catálogo cobertas?
87
+ 4. seu agente liga cada caso ao teste real com o marcador `# cenario: <nome exato do caso>`
88
+ 5. `sentry run --spec cadastro-de-cliente --run-tests` — roda a suíte, lê diff e cobertura, aplica as regras, persiste
89
+ 6. `sentry report` / `sentry history` — releitura e comparação entre execuções
90
+
91
+ Todo passo também funciona sem agente, pelos comandos abaixo.
92
+
93
+ ## Comandos
94
+
95
+ Código de saída `0` em sucesso; veja a tabela de códigos adiante.
96
+
97
+ | Comando | O que faz |
98
+ | --- | --- |
99
+ | `sentry init [--install]` | Prepara o repositório: `.sentry/`, `sentry.toml`, `.gitignore`, guia de agente e skills. Com `--install`, instala as dependências ausentes. |
100
+ | `sentry new <nome> [--prompt "..."] [--json]` | Cria a pasta da spec com slug derivado do nome. `--json` emite template, vocabulário aceito e classes cobradas, para o agente consumir. |
101
+ | `sentry check [<slug>\|all]` | Valida `CASES.md`: estrutura, vocabulário e cobrança de classes de equivalência. `all` valida todas as specs juntas. |
102
+ | `sentry run [--spec <slug>\|all] [--run-tests]` | Executa a análise e persiste. Sem `--run-tests` não há cobertura, e o veredito tende a `inconclusivo`. |
103
+ | `sentry report` | Exibe o último relatório (`.sentry/reports/latest.md`). |
104
+ | `sentry history` | Lista execuções e compara as duas últimas: cobertura, testes, achados novos, resolvidos e persistentes. |
105
+ | `sentry clear [--keep-last N] [--yes]` | Poda execuções e relatórios antigos. Sem `--yes` apenas mostra o que sairia — apagar histórico é irreversível. Nunca toca em `.sentry/specs/`. |
106
+
107
+ ## Códigos de saída
108
+
109
+ Quatro estados distinguíveis, para separar "código mal testado" de "meu ambiente quebrou":
110
+
111
+ | Código | Significado |
112
+ | --- | --- |
113
+ | `0` | aprovado |
114
+ | `1` | aprovado com ressalvas |
115
+ | `2` | reprovado |
116
+ | `3` | inconclusivo ou erro de infraestrutura |
117
+
118
+ Erro de infraestrutura nunca produz veredito aprovado: uma suíte que não conseguiu rodar é diferente de uma suíte que reprovou.
119
+
120
+ `sentry check` mantém semântica própria: `0` estrutura válida, `1` erros estruturais, `2` não foi possível resolver a spec.
121
+
122
+ ## Skills
123
+
124
+ Geradas para cada agente configurado; o `AGENT-SENTRY.md` cobre os demais.
125
+
126
+ | Workflow | O que o agente faz |
127
+ | --- | --- |
128
+ | `sentry-cases` | Recebe o pedido em texto livre, cria a spec, **pergunta antes de escrever** toda ambiguidade que mude um caso, preenche o `CASES.md`, liga cada caso ao teste com `# cenario:` e roda `check` até fechar limpo. Nunca escreve status. |
129
+
130
+ ## Regras determinísticas
131
+
132
+ Dez regras, com severidade configurável por projeto.
133
+
134
+ | Regra | Severidade padrão | Dispara quando |
135
+ | --- | --- | --- |
136
+ | `test-failing` | crítica | a suíte tem teste falhando |
137
+ | `case-spec-invalid` | crítica | o `CASES.md` tem erro estrutural |
138
+ | `changed-code-uncovered` | alta | cobertura do código alterado é zero |
139
+ | `scenario-without-test` | alta | caso declarado sem teste associado |
140
+ | `error-path-without-test` | alta | `raise`/`throw` em linha alterada que nenhum teste executou |
141
+ | `missing-equivalence-class` | alta | classe exigida pelo catálogo que nenhum caso cobre |
142
+ | `coverage-below-threshold` | alta | cobertura do código alterado abaixo do limiar declarado |
143
+ | `requirement-without-scenario` | média | requisito sem cenário correspondente |
144
+ | `coverage-missing` | média | não foi possível calcular a cobertura do código alterado |
145
+ | `global-coverage-below-threshold` | média | cobertura global abaixo do limiar declarado |
146
+
147
+ Sem limiar declarado, o Sentry não inventa um mínimo. Quem define "quanto basta" é o projeto, e o relatório registra o número aplicado.
148
+
149
+ ## Catálogo de classes de equivalência
150
+
151
+ Tabela fixa de situações que precisam de teste, **por tipo de campo**. Não gera casos: cobra os que o agente deixou de declarar.
152
+
153
+ Tipos conhecidos: `cpf`, `cnpj`, `email`, `senha`, `data`, `telefone`, `cep`, `inteiro`, `decimal`, `texto`, `rota`.
154
+
155
+ Uma classe que não faz sentido para o campo pode ser dispensada **com justificativa**, em vez de virar caso artificial ou cobrança eterna:
156
+
157
+ ```markdown
158
+ ## Classes não aplicáveis
159
+
160
+ - **exclude/tamanho-maximo-excedido**: é parâmetro de configuração, não campo de formulário
161
+ ```
162
+
163
+ A dispensa remove o achado, mas fica registrada no relatório — nada some em silêncio.
164
+
165
+ ## Dimensões de cobertura
166
+
167
+ Cada uma reporta `coberta`, `parcial`, `não coberta` ou `não aplicável`, com evidência.
168
+
169
+ | Dimensão | De onde tira a evidência |
170
+ | --- | --- |
171
+ | requisitos e regras de negócio | cenários da spec com teste associado |
172
+ | APIs, persistência, transações e integrações | casos de tipo `contrato`/`integração` e camada `integração` |
173
+ | exceções, resiliência e recuperação | caminhos de erro alterados executados por algum teste |
174
+ | segurança e autorização | campos de tipo `rota` com todas as classes de acesso cobertas |
175
+
176
+ `não aplicável` é distinto de `não coberta`: um projeto sem rotas não é punido na dimensão de segurança.
177
+
178
+ ## Configuração
179
+
180
+ `sentry.toml` na raiz, versionável, sem segredos. Tudo é opcional além do que o `init` já escreve.
181
+
182
+ ```toml
183
+ [project]
184
+ name = "meu-projeto"
185
+
186
+ [specs]
187
+ path = ".sentry/specs"
188
+
189
+ [test] # qualquer executor que exporte JUnit XML
190
+ command = "npx jest"
191
+ junit_xml = "reports/junit.xml" # sem isto, o Sentry injeta --junitxml (pytest)
192
+
193
+ [tests] # onde procurar testes
194
+ paths = ["tests"] # padrão: tests, test, spec, __tests__
195
+
196
+ [coverage] # relatório gerado pela suíte do próprio projeto
197
+ path = "coverage/lcov.info"
198
+ format = "lcov" # opcional: detectado pelo conteúdo quando omitido
199
+
200
+ [analysis]
201
+ run_tests_by_default = false
202
+ timeout_seconds = 300
203
+ exclude = ["frontend/"] # diretórios fora do escopo da análise
204
+
205
+ [policy.thresholds] # sem isto, nenhum mínimo é cobrado
206
+ changed_coverage = 85
207
+ global_coverage = 90
208
+
209
+ [policy.severities] # sobrescreve a severidade de qualquer regra
210
+ coverage-missing = "alta"
211
+
212
+ [catalog.fields] # tipos de campo do seu domínio
213
+ matricula = ["vazio", "formato-invalido", "valida"]
214
+
215
+ [dimensions] # eixos que não se aplicam ao projeto
216
+ disabled = []
217
+ ```
218
+
219
+ `.sentry/` guarda specs, execuções, relatórios e o banco. Fica fora do Git, com uma exceção deliberada: `.sentry/reports/latest.md` é versionado, para o veredito aparecer no diff da PR sem que o revisor precise rodar o Sentry.
220
+
221
+ O histórico é mantido indefinidamente, e cresce a cada execução. Para podar:
222
+
223
+ ```bash
224
+ sentry clear --keep-last 10 # mostra o que sairia
225
+ sentry clear --keep-last 10 --yes # remove
226
+ ```
227
+
228
+ As specs nunca são removidas: são intenção declarada, não evidência gerada.
229
+
230
+ ## Stacks suportadas
231
+
232
+ A **derivação** — do pedido à matriz de casos — é agnóstica de linguagem: o `CASES.md` é markdown e o catálogo raciocina sobre tipo de dado, não sobre código.
233
+
234
+ A **verificação** depende do formato de intercâmbio que sua suíte exporta, não da ferramenta:
235
+
236
+ | Capacidade | Suporte |
237
+ | --- | --- |
238
+ | Execução da suíte | qualquer comando que exporte **JUnit XML** — pytest, Jest, Vitest, `go test` (gotestsum), Surefire, `dotnet test`, RSpec, PHPUnit |
239
+ | Cobertura | **lcov** (nyc, c8, Jest, simplecov), **Cobertura XML** (JaCoCo, coverlet), **coverage.py** (JSON) — detectados pelo conteúdo |
240
+ | Rastreabilidade caso↔teste | `.py`, `.js`/`.jsx`/`.ts`/`.tsx`, `.go`, `.java`/`.kt`, `.cs`, `.rb`, `.php`, `.rs` — e o marcador `cenario:` funciona em qualquer comentário |
241
+ | Caminhos de erro | por AST em Python; por padrão sintático (`throw`, `catch`, `panic`, `rescue`, `panic!`) nas demais |
242
+ | Análise de impacto | 12 extensões de código-fonte |
243
+
244
+ A detecção de caminho de erro fora de Python é menos precisa que AST, e o relatório registra essa diferença como limitação — nunca a esconde.
245
+
246
+ Camada `frontend` é recusada de propósito: sem adaptador que a verifique, um caso declarado ficaria preso em `não coberto` para sempre.
247
+
248
+ ## Local-first
249
+
250
+ Nenhuma telemetria, nenhuma chamada externa, nenhum envio de código ou diff. Todo o histórico permanece na máquina.
251
+
252
+ ## Desenvolvimento
253
+
254
+ ```bash
255
+ python -m pip install -e .
256
+ python -m pytest
257
+ ```
258
+
259
+ O Sentry se analisa: `sentry run --spec all --run-tests` na raiz do repositório
260
+ casa os casos declarados em `.sentry/specs/` com as funções de teste reais e
261
+ reporta as quatro dimensões.
262
+
263
+ ## Licença
264
+
265
+ MIT
@@ -0,0 +1,233 @@
1
+ # Sentry
2
+
3
+ CLI de qualidade de teste orientada a mudança. O `sentry` cria a pasta da spec, valida a matriz de casos em markdown, roda a suíte, lê o diff e a cobertura, e emite um veredito auditável — e deixa o fluxo escrito para o agente de IA que for implementar a mudança.
4
+
5
+ Markdown é a fonte da intenção: a CLI parseia e valida `CASES.md` e `PROMPT.md` — ela nunca os escreve. O agente de IA faz a redação; o Sentry garante estrutura, rastreabilidade e veredito.
6
+
7
+ > Não confundir com o [Sentry da getsentry](https://sentry.io) (monitoramento de erros). Este projeto é distribuído como `sentry-test`.
8
+
9
+ ## A divisão de responsabilidade
10
+
11
+ - **O agente de IA declara intenção** — escreve o `CASES.md`: requisito, camada, tipo, prioridade, entrada, resultado esperado.
12
+ - **O Sentry mede a realidade** — decide status, teste associado, evidência e veredito.
13
+
14
+ O agente nunca escreve status. O Sentry nunca chama um modelo. É isso que torna o veredito auditável e reproduzível.
15
+
16
+ ## Instalação
17
+
18
+ ```bash
19
+ pip install sentry-test
20
+ ```
21
+
22
+ Requer Python 3.11+. Confira com `sentry --version` (imprime a versão do pacote).
23
+
24
+ Se faltar `pytest` ou `coverage`, o `init` avisa. Para instalar junto:
25
+
26
+ ```bash
27
+ sentry init --install
28
+ ```
29
+
30
+ ## Setup
31
+
32
+ ```bash
33
+ cd seu-projeto
34
+ sentry init
35
+ ```
36
+
37
+ Cria `.sentry/` (specs, execuções, relatórios e banco), o `sentry.toml`, as entradas do `.gitignore`, e escreve o fluxo em dois lugares:
38
+
39
+ - **Skill `sentry-cases`** em `.claude/skills/sentry-cases/SKILL.md` — carregada automaticamente pelo Claude Code e por agentes que seguem essa convenção.
40
+ - **`AGENT-SENTRY.md`** na raiz do projeto — o mesmo fluxo em markdown puro, sem depender de convenção de nenhuma ferramenta.
41
+
42
+ Para outros agentes (Cursor, Windsurf, Codex, opencode), aponte-os para o `AGENT-SENTRY.md` no arquivo de regras que cada um já usa — por exemplo, uma linha em `.cursor/rules` ou `AGENTS.md`:
43
+
44
+ ```markdown
45
+ Para escrever ou revisar casos de teste, siga AGENT-SENTRY.md.
46
+ ```
47
+
48
+ `init` é idempotente: não apaga histórico, não sobrescreve configuração existente, não duplica estruturas.
49
+
50
+ ## O fluxo
51
+
52
+ 1. `sentry new "cadastro de cliente"` — cria `.sentry/specs/cadastro-de-cliente/` com `PROMPT.md` (pedido preservado) e `CASES.md` em branco
53
+ 2. **`sentry-cases`** — seu agente pergunta o que estiver ambíguo e preenche o `CASES.md` seguindo o template
54
+ 3. `sentry check cadastro-de-cliente` — estrutura válida? classes de equivalência do catálogo cobertas?
55
+ 4. seu agente liga cada caso ao teste real com o marcador `# cenario: <nome exato do caso>`
56
+ 5. `sentry run --spec cadastro-de-cliente --run-tests` — roda a suíte, lê diff e cobertura, aplica as regras, persiste
57
+ 6. `sentry report` / `sentry history` — releitura e comparação entre execuções
58
+
59
+ Todo passo também funciona sem agente, pelos comandos abaixo.
60
+
61
+ ## Comandos
62
+
63
+ Código de saída `0` em sucesso; veja a tabela de códigos adiante.
64
+
65
+ | Comando | O que faz |
66
+ | --- | --- |
67
+ | `sentry init [--install]` | Prepara o repositório: `.sentry/`, `sentry.toml`, `.gitignore`, guia de agente e skills. Com `--install`, instala as dependências ausentes. |
68
+ | `sentry new <nome> [--prompt "..."] [--json]` | Cria a pasta da spec com slug derivado do nome. `--json` emite template, vocabulário aceito e classes cobradas, para o agente consumir. |
69
+ | `sentry check [<slug>\|all]` | Valida `CASES.md`: estrutura, vocabulário e cobrança de classes de equivalência. `all` valida todas as specs juntas. |
70
+ | `sentry run [--spec <slug>\|all] [--run-tests]` | Executa a análise e persiste. Sem `--run-tests` não há cobertura, e o veredito tende a `inconclusivo`. |
71
+ | `sentry report` | Exibe o último relatório (`.sentry/reports/latest.md`). |
72
+ | `sentry history` | Lista execuções e compara as duas últimas: cobertura, testes, achados novos, resolvidos e persistentes. |
73
+ | `sentry clear [--keep-last N] [--yes]` | Poda execuções e relatórios antigos. Sem `--yes` apenas mostra o que sairia — apagar histórico é irreversível. Nunca toca em `.sentry/specs/`. |
74
+
75
+ ## Códigos de saída
76
+
77
+ Quatro estados distinguíveis, para separar "código mal testado" de "meu ambiente quebrou":
78
+
79
+ | Código | Significado |
80
+ | --- | --- |
81
+ | `0` | aprovado |
82
+ | `1` | aprovado com ressalvas |
83
+ | `2` | reprovado |
84
+ | `3` | inconclusivo ou erro de infraestrutura |
85
+
86
+ Erro de infraestrutura nunca produz veredito aprovado: uma suíte que não conseguiu rodar é diferente de uma suíte que reprovou.
87
+
88
+ `sentry check` mantém semântica própria: `0` estrutura válida, `1` erros estruturais, `2` não foi possível resolver a spec.
89
+
90
+ ## Skills
91
+
92
+ Geradas para cada agente configurado; o `AGENT-SENTRY.md` cobre os demais.
93
+
94
+ | Workflow | O que o agente faz |
95
+ | --- | --- |
96
+ | `sentry-cases` | Recebe o pedido em texto livre, cria a spec, **pergunta antes de escrever** toda ambiguidade que mude um caso, preenche o `CASES.md`, liga cada caso ao teste com `# cenario:` e roda `check` até fechar limpo. Nunca escreve status. |
97
+
98
+ ## Regras determinísticas
99
+
100
+ Dez regras, com severidade configurável por projeto.
101
+
102
+ | Regra | Severidade padrão | Dispara quando |
103
+ | --- | --- | --- |
104
+ | `test-failing` | crítica | a suíte tem teste falhando |
105
+ | `case-spec-invalid` | crítica | o `CASES.md` tem erro estrutural |
106
+ | `changed-code-uncovered` | alta | cobertura do código alterado é zero |
107
+ | `scenario-without-test` | alta | caso declarado sem teste associado |
108
+ | `error-path-without-test` | alta | `raise`/`throw` em linha alterada que nenhum teste executou |
109
+ | `missing-equivalence-class` | alta | classe exigida pelo catálogo que nenhum caso cobre |
110
+ | `coverage-below-threshold` | alta | cobertura do código alterado abaixo do limiar declarado |
111
+ | `requirement-without-scenario` | média | requisito sem cenário correspondente |
112
+ | `coverage-missing` | média | não foi possível calcular a cobertura do código alterado |
113
+ | `global-coverage-below-threshold` | média | cobertura global abaixo do limiar declarado |
114
+
115
+ Sem limiar declarado, o Sentry não inventa um mínimo. Quem define "quanto basta" é o projeto, e o relatório registra o número aplicado.
116
+
117
+ ## Catálogo de classes de equivalência
118
+
119
+ Tabela fixa de situações que precisam de teste, **por tipo de campo**. Não gera casos: cobra os que o agente deixou de declarar.
120
+
121
+ Tipos conhecidos: `cpf`, `cnpj`, `email`, `senha`, `data`, `telefone`, `cep`, `inteiro`, `decimal`, `texto`, `rota`.
122
+
123
+ Uma classe que não faz sentido para o campo pode ser dispensada **com justificativa**, em vez de virar caso artificial ou cobrança eterna:
124
+
125
+ ```markdown
126
+ ## Classes não aplicáveis
127
+
128
+ - **exclude/tamanho-maximo-excedido**: é parâmetro de configuração, não campo de formulário
129
+ ```
130
+
131
+ A dispensa remove o achado, mas fica registrada no relatório — nada some em silêncio.
132
+
133
+ ## Dimensões de cobertura
134
+
135
+ Cada uma reporta `coberta`, `parcial`, `não coberta` ou `não aplicável`, com evidência.
136
+
137
+ | Dimensão | De onde tira a evidência |
138
+ | --- | --- |
139
+ | requisitos e regras de negócio | cenários da spec com teste associado |
140
+ | APIs, persistência, transações e integrações | casos de tipo `contrato`/`integração` e camada `integração` |
141
+ | exceções, resiliência e recuperação | caminhos de erro alterados executados por algum teste |
142
+ | segurança e autorização | campos de tipo `rota` com todas as classes de acesso cobertas |
143
+
144
+ `não aplicável` é distinto de `não coberta`: um projeto sem rotas não é punido na dimensão de segurança.
145
+
146
+ ## Configuração
147
+
148
+ `sentry.toml` na raiz, versionável, sem segredos. Tudo é opcional além do que o `init` já escreve.
149
+
150
+ ```toml
151
+ [project]
152
+ name = "meu-projeto"
153
+
154
+ [specs]
155
+ path = ".sentry/specs"
156
+
157
+ [test] # qualquer executor que exporte JUnit XML
158
+ command = "npx jest"
159
+ junit_xml = "reports/junit.xml" # sem isto, o Sentry injeta --junitxml (pytest)
160
+
161
+ [tests] # onde procurar testes
162
+ paths = ["tests"] # padrão: tests, test, spec, __tests__
163
+
164
+ [coverage] # relatório gerado pela suíte do próprio projeto
165
+ path = "coverage/lcov.info"
166
+ format = "lcov" # opcional: detectado pelo conteúdo quando omitido
167
+
168
+ [analysis]
169
+ run_tests_by_default = false
170
+ timeout_seconds = 300
171
+ exclude = ["frontend/"] # diretórios fora do escopo da análise
172
+
173
+ [policy.thresholds] # sem isto, nenhum mínimo é cobrado
174
+ changed_coverage = 85
175
+ global_coverage = 90
176
+
177
+ [policy.severities] # sobrescreve a severidade de qualquer regra
178
+ coverage-missing = "alta"
179
+
180
+ [catalog.fields] # tipos de campo do seu domínio
181
+ matricula = ["vazio", "formato-invalido", "valida"]
182
+
183
+ [dimensions] # eixos que não se aplicam ao projeto
184
+ disabled = []
185
+ ```
186
+
187
+ `.sentry/` guarda specs, execuções, relatórios e o banco. Fica fora do Git, com uma exceção deliberada: `.sentry/reports/latest.md` é versionado, para o veredito aparecer no diff da PR sem que o revisor precise rodar o Sentry.
188
+
189
+ O histórico é mantido indefinidamente, e cresce a cada execução. Para podar:
190
+
191
+ ```bash
192
+ sentry clear --keep-last 10 # mostra o que sairia
193
+ sentry clear --keep-last 10 --yes # remove
194
+ ```
195
+
196
+ As specs nunca são removidas: são intenção declarada, não evidência gerada.
197
+
198
+ ## Stacks suportadas
199
+
200
+ A **derivação** — do pedido à matriz de casos — é agnóstica de linguagem: o `CASES.md` é markdown e o catálogo raciocina sobre tipo de dado, não sobre código.
201
+
202
+ A **verificação** depende do formato de intercâmbio que sua suíte exporta, não da ferramenta:
203
+
204
+ | Capacidade | Suporte |
205
+ | --- | --- |
206
+ | Execução da suíte | qualquer comando que exporte **JUnit XML** — pytest, Jest, Vitest, `go test` (gotestsum), Surefire, `dotnet test`, RSpec, PHPUnit |
207
+ | Cobertura | **lcov** (nyc, c8, Jest, simplecov), **Cobertura XML** (JaCoCo, coverlet), **coverage.py** (JSON) — detectados pelo conteúdo |
208
+ | Rastreabilidade caso↔teste | `.py`, `.js`/`.jsx`/`.ts`/`.tsx`, `.go`, `.java`/`.kt`, `.cs`, `.rb`, `.php`, `.rs` — e o marcador `cenario:` funciona em qualquer comentário |
209
+ | Caminhos de erro | por AST em Python; por padrão sintático (`throw`, `catch`, `panic`, `rescue`, `panic!`) nas demais |
210
+ | Análise de impacto | 12 extensões de código-fonte |
211
+
212
+ A detecção de caminho de erro fora de Python é menos precisa que AST, e o relatório registra essa diferença como limitação — nunca a esconde.
213
+
214
+ Camada `frontend` é recusada de propósito: sem adaptador que a verifique, um caso declarado ficaria preso em `não coberto` para sempre.
215
+
216
+ ## Local-first
217
+
218
+ Nenhuma telemetria, nenhuma chamada externa, nenhum envio de código ou diff. Todo o histórico permanece na máquina.
219
+
220
+ ## Desenvolvimento
221
+
222
+ ```bash
223
+ python -m pip install -e .
224
+ python -m pytest
225
+ ```
226
+
227
+ O Sentry se analisa: `sentry run --spec all --run-tests` na raiz do repositório
228
+ casa os casos declarados em `.sentry/specs/` com as funções de teste reais e
229
+ reporta as quatro dimensões.
230
+
231
+ ## Licença
232
+
233
+ MIT
@@ -0,0 +1,21 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "sentry-test"
7
+ version = "1.0.0"
8
+ description = "Test quality intelligence for change-oriented reviews"
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = { file = "LICENSE" }
12
+ authors = [{ name = "Lucas Nicolau Ferreira" }]
13
+
14
+ [project.scripts]
15
+ sentry = "sentrytest.cli:main"
16
+
17
+ [tool.setuptools.packages.find]
18
+ where = ["src"]
19
+
20
+ [tool.pytest.ini_options]
21
+ testpaths = ["tests"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+